Skip to content

HR & Payroll in Depth

BigLedger keeps a record of every employee and runs expense claims through to the point where a line is paid by finance or handed to payroll. Salaries are not calculated here: payroll runs in whatever system computes it, and the monthly result comes into BigLedger as a general journal. This page is what happens behind the people screens; the applets are listed on the HR & Payroll module page.

The employee record is an entity

There is one entity table in BigLedger. Customers, suppliers, employees and merchants are rows in it with four flags, and the same person can carry more than one. Employee Maintenance shows the employment fields only while EMPLOYEE is among the record’s types; Entity Maintenance shows every record regardless of type. Two consequences follow:

  • An employee who is also a customer is one record, not two. The CSV import matches on employee code first and, failing that, on ID number, tax number, e-mail and phone against all entities — so a row without an employee code can update an existing customer and flag it as an employee rather than create a new person.
  • Employee codes are generated from the EMPLOYEE_ID running number and the tenant’s employee prefix when you leave the field blank. Set the prefix before the first import if you want codes with the prefix you chose.

What reaches the ledger

Employee Maintenance and Entity Maintenance write master data and post no journal. The two claims applets post no journal, move no stock and create no payment voucher — a claim is not a generic financial document and has no entry in the platform’s journal-posting handler for the claim itself. Money for a Salary Payment claim line leaves the business through payroll; a Finance Payment line reaches the books on the Payment Voucher (Internal) a person raises from the cycle’s PV Details Report.

Payroll’s Post GL does not reach the general ledger. It writes three lines into the payroll module’s own journal tables and nothing anywhere else — no entry reaches the chart of accounts balances, the trial balance or any financial report, and the pay run still reads POSTED afterwards. The columns that would link it to a financial journal exist and nothing ever sets them. The detail, with the source, is on the Payroll Admin page.

So bringing payroll into the accounts is a person’s job, and it is a manual journal. Whoever keeps the books posts it in the month the work was done — not the month it was paid — debiting wages expense with gross plus the employer’s contributions, crediting net pay to a payable and both halves of the statutory contributions to their liability accounts. You know it worked when the wages expense in the trial balance equals the payroll system’s gross plus employer contributions for that month, and the statutory liability clears to nil when you remit on the 15th.

What this module does not do today

Worth stating plainly:

  • No leave record. Employee Maintenance has an Approved Leave tab, and it saves nothing — its add handler is empty and its save call is commented out. Do not use it to record leave. Leave balances stay wherever they are kept today — a spreadsheet, an HR system, a wall chart. What payroll needs from that record is one number a month, the unpaid-leave days, agreed with the line manager before the salary cut-off; the check is that the days keyed into the pay match the approved leave register for the same period.
  • No attendance capture. No registered applet writes a clock-in or clock-out event. Hours come from whatever records them, and the conversion to pay is a rule the business writes down once — which divisor turns a monthly salary into an hourly rate, and what multiplier applies to a rest day. The check is that the same salary produces the same hourly rate for two different people in two different months.
  • No approval engine of its own outside Claims. Claims has one, always on, with its own approval settings. Who approves leave, overtime and a pay change is therefore a written policy, not a setting. Name one authoritative source for the reporting line — the org chart, the Report To fields or the claims branch designations — and say which; the check is that a manager can list everyone whose time they approve and the list matches the source you chose.
  • No salary, no payslip, no statutory calculation you can use today. A Malaysian payroll backend exists and is described at Payroll Admin, and the applet is not registered. This wiki does not publish EPF, SOCSO, EIS or PCB rate tables: take them from KWSP, PERKESO and LHDN, and note that whoever computes your payroll today should be on LHDN’s published list of payroll software whose PCB calculation it has verified — BigLedger is not yet on it.

Where the people figures come from

Most questions about this module start with a number or a name that looks wrong. Each figure below was either written once and kept, or is worked out again every time you look — and knowing which tells you where to look.

The figureWritten when, from whatSo, when it looks wrong
A new employee’s codeGenerated by the server when the record is saved with the code left blank: the EMPLOYEE_ID running number plus the tenant’s employee prefix as it stood at that momentCodes with the wrong prefix were saved before the prefix was set; nothing renumbers them (Configuration, Step 2)
The salesperson’s name and code on an invoiceCopied onto the document when the salesperson was picked, and kept. Merging two entity records is the one route that rewrites themAn old invoice shows the old name after a rename — the copy doing its job, because a reprint has to match the original (Employee Maintenance)
The claimant’s name and code on a claim lineCopied from the employee record at SubmitA rename does not reach lines already submitted
The Payroll Payment ReportWorked out each time you run it, from Salary Payment claim lines. With a Claim Cycle chosen it lists only the lines attached to that cycle — and a line is attached at its last approval, to its company’s cycle for that month, only if the cycle already exists and the approval falls on or before the cycle’s approval cut-offA line approved after the cut-off is on no cycle’s list. Run the report with Claim Cycle left empty (Claim Cycle, Troubleshooting)
The Bank Report’s rows and account numbersStored at the time you press Generate: approved Finance Payment lines per employee, with the bank code and account number read from each employee’s Payment Config at that momentYou filled a missing Payment Config and the row is still blank — generate the report again (Claims, Where the claim figures come from)
A reimbursement in the general ledgerFrom the journal of the Payment Voucher (Internal) a person raises from the PV Details Report, dated the voucher’s dateA March claim paid on a voucher dated 5 April is an April expense
Wages expense in the trial balanceFrom the general journal a person posts from the payroll result. Nothing in this module writes it, and Payroll Admin’s Post GL writes only into the payroll module’s own tablesWages are nil for a month: the journal was not posted, or was dated into the month it was paid

One month at GadgetSphere, followed through

Take, for example, March at GadgetSphere Sdn Bhd (GS). The figures are illustrative.

Twelve new hires on 2 March. You load them with File Import in Employee Maintenance, with EMPLOYEE_CODE on eleven rows. The twelfth, keyed in a hurry with no code, is matched by phone number to a walk-in customer record from last year and flagged as an employee — one record, two roles. That is harmless here, but it is not what you meant, and it is why the code goes on every row. Each new hire is then invited from the Login tab, their Main-tab e-mail set to the address they will sign in with, and their bank account entered on Payment Config.

A claim approved too late for the list. GS pays mileage with salary. A GS-KV-01 supervisor’s RM 280 mileage line gets its last approval on 24 March, inside the March cycle’s approval cut-off of 25 March, and appears on that cycle’s Payroll Payment tab. A second line, RM 64, is approved on 28 March — after the cut-off — and joins no cycle. If whoever runs payroll reads only the March cycle’s tab, the RM 64 is never paid. Run with Claim Cycle left empty, the report shows both.

The payroll journal. Payroll is computed by a bureau. Its March summary arrives on 27 March: gross pay RM 512,400, employees’ statutory deductions RM 78,950, employer’s contributions RM 70,180, net pay RM 433,450. In Ledger And Journal you post one general journal dated 31 March: debit EXPENSE-WAGES RM 582,580 (gross plus the employer’s share), split into one line per branch; credit a net-pay payable RM 433,450; credit each statutory scheme’s liability with both halves of its contribution, RM 149,130 between them. Salaries leave the primary bank on 1 April, clearing the net-pay payable; the contributions are remitted by 15 April and each liability returns to nil. March carries the cost, although no money moved in March.

A leaver. A cashier at GS-KV-03 resigns on 20 March. You set Employment Status to RESIGNED and the Cessation Date, and leave the record ACTIVE until their last claim is paid. Then you set it INACTIVE. That takes them out of the Sales Invoice and point-of-sale salesperson pickers at once — but not out of the Sales Order, Quotation or Delivery Order pickers, which list employees by category whatever their status, and not out of Claims. Had they been a claims reviewer, you would also remove their row in the Claim Cycle applet’s Reviewer Setting.

How the pieces depend on each other

What must exist first. Companies and branches in Organization — every employee needs a branch to save. The employee prefix, before the first record. A platform login for anyone who will claim, linked from the employee’s Login tab, with the same address on the Main tab. And for Claims, its own settings: designations per branch, approval settings and one cut-off row per company. Configuration puts them in order and says what each gap looks like.

What a complete employee record makes possible. It lets you name a salesperson on sales documents and at the till, which is what commission is calculated from; link an account manager to the customers they look after; raise a self-billed e-Invoice to the employee; put a spending limit on their purchases at the till; and submit claims. Each of these reads a different field of the record, so a record can be complete enough for one and not for another (Employee Maintenance, Who reads an employee record).

Siblings, and when to use which.

  • Employee Maintenance or Entity Maintenance? Create employees, link their logins and keep their employment fields in Employee Maintenance. Use Entity Maintenance when an existing customer or supplier also becomes an employee, rather than creating a second record for the same person.
  • Salary Payment or Finance Payment on a claim item? Salary Payment for small, regular claims you would rather add to pay than transfer one by one; Finance Payment for anything that should be reviewed in the claim cycle and paid from the Bank Report.
  • Payment Voucher (Internal) or Reimbursement Payment Voucher? When finance pays claims, record anything carrying tax on a Payment Voucher (Internal); a taxed line on a Reimbursement Payment Voucher leaves its journal unwritten (Claims, Which one to choose).
  • Entity status or Employment Status? Employment Status records why and when a person left; the entity status INACTIVE is what takes them out of the pickers that check it. A leaver needs both.

What breaks elsewhere when an employee record is wrong.

  • The Main-tab e-mail. Claims finds the signed-in person by comparing their login e-mail with this field, so a missing or different address fails with Cannot find your email … from Employee Applet, and two records sharing one address resolve to whichever the database returns first.
  • The Employee Category. Most sales document applets list salespeople by category, so an employee with none is missing from the Sales Order picker while present in the Sales Invoice one.
  • The Category tab and commission. A commission rule on employee category reads a different field from the one this tab writes, so a scheme built on it matches nobody.
  • Payment Config. A claimant without one gets a Bank Report row with no account, and is not paid until somebody notices.

What it pairs with in practice. Across the companies on BigLedger, employee records are common, many companies name a salesperson on their sales documents, and expense claims are run by very few. So for most readers this module is the employee master behind sales and commission, used alongside a payroll that runs somewhere else — and the payroll journal in Ledger And Journal is the module’s other half.

When it goes wrong

SymptomCauseFix
Cannot find your email … from Employee Applet when someone opens ClaimsNo employee record carries the address they sign in withSet that exact address on the Main tab (Employee Maintenance, Troubleshooting)
A claim was submitted, and the claimant’s own list is emptyThe Login tab has no link for their loginLink the login on the employee’s Login tab
A salesperson is in the Sales Invoice picker and missing from the Sales Order oneThe Sales Order picker lists employees by category, and they have noneAdd an Employee Category
A deactivated salesperson still appears on new sales ordersThe same category-based picker does not check statusExpected; only the Sales Invoice and till pickers check it
A leaver is still approving or reviewing claimsEmployment Status is a label, and the claims lookups do not check ACTIVERemove their Reviewer Setting row in the Claim Cycle applet, and set the record INACTIVE
The CSV import updated an existing customer rather than creating an employeeThe row had no EMPLOYEE_CODE, so it was matched on ID, tax number, e-mail and phone against every entityPut a code on every row (Best practices §2)
A Bank Report row has no bank code or account numberNo Payment Config on that employee when the report was generatedFill it, then generate the report again
An approved Salary Payment claim never reached a payslipIt was approved after its cycle’s approval cut-off, so it is on no cycle’s listRun the Payroll Payment Report with Claim Cycle empty and your company chosen (it returns at most 1,000 lines, from every month); turn on Auto-add approved claims to active cycle, and look at last month’s cycle tab again after export, because a late line joins it after the cut-off (Claim Cycle, Troubleshooting)
Wages in the trial balance do not equal the payroll system’s gross plus employer contributionsThe month’s journal is missing, dated into the payment month, or posted twiceFind it in Ledger And Journal by its reference and date, with the listing’s Type filter left empty — an imported journal matches neither MANUAL nor AUTO — before posting again
A branch’s wages read nil in a per-branch reportThe journal lines carry no branch. A line’s branch is optional, a keyed journal’s header branch is not copied to its lines, and per-branch reports drop a branchless linePick the branch on each keyed line, or fill LINE_BRANCH_CODE on every imported row (Ledger And Journal)
A payroll journal file ended FAILED, and some of its journals are in the ledgerOnce rows pass validation, a refused journal group is skipped while the others postCheck the journal listing before uploading again, or the good ones post twice
Leave keyed on the Approved Leave tab has vanishedThe tab saves nothingKeep leave where you keep it today (What this module does not do today)

How you know it worked

Three checks, each under a minute.

  1. After adding an employee. Raise a draft sales invoice and a draft sales order at their branch and find them in both salesperson pickers. If they claim, sign in as them and open My Claim: it loads, so the e-mail matches.
  2. After posting the payroll journal. The month’s wages expense in the trial balance equals the payroll system’s gross plus the employer’s contributions, and every line names a branch.
  3. After the 15th. Each statutory liability account reads nil, and the Payroll Payment Report run with Claim Cycle left empty and your company chosen lists nothing that is missing from a payslip. It returns at most 1,000 lines from every month with no date filter, so a list of exactly 1,000 may be cut short and proves nothing.

If one fails, the row above with the same symptom names the page that fixes it.

Read next