Comprehensive HR Management System

While OpenERP is a great basic framework for an ERP system it’s not really meant as a final solution.  While some areas are fairly well advanced some other areas are not. One of these areas is Human Resources. Any implementation in a real business will require a not-inconsiderable amount of work to get it to a usable state. With this in mind for the past several months I have been busy implementing a comprehensive HR Management System that should provide a very firm foundation for further work in this area.  While this system is already in use in a company with over 600 employees, it is still in active development and will continue to improve over the coming months. You can get it here.

There are four broad areas these modules cover:

  1. Managing Employee and Contract State
  2. Attendance and Scheduling
  3. Leave Management
  4. Payroll Management

Managing Employee and Contract State

The main modules implementing this functionality are: hr_contract_reference, hr_contract_state, hr_employee_id, hr_employee_profile, hr_employee_state, hr_labour_recruitment, hr_transfer, hr_wage_increment

Managing employee and contract state is essential for the attendance and payroll processing systems to work properly. These modules provide workflows to manage employees and their contracts from the time they are hired until they are de-activated from the system.

Attendance and Scheduling

There is one module implementing this: hr_schedule.

This module allows you to create a schedule for each employee based on a schedule template attached to the employee’s contract. There is a cron job that simplifies this process by automatically creating schedules in two week blocks every two weeks.  It also integrates with the leave management modules to modify an employee’s schedule according to the employee’s leaves. This module also provides Scheduling Exceptions to warn you of abnormal situations such as employees coming late or leaving early, not showing up for work, etc. However, this part of the module needs some more work to make it more usable.

Actually, there is also another module, hr_attendance_batch_entry, but it contains some bits that assume behavior highly specific to my own circumstance, and wouldn’t work for another company. None the less it offers useful functionality that allows time keepers to enter weekly attendance data per department quickly and easily (which is quite handy when you have to enter attendance data for 600+ employees).

Leave Management

The modules implementing this functionality are: hr_holidays_extension, hr_public_holidays, hr_accrual, hr_policy_accrual.

The biggest benefit is provided by hr_accrual  and hr_policy_accrual. These two modules implement functionality that makes annual leave management a “fire and forget” proposition.  An accrual policy allows you to specify the rules according to which days are accrued and how they are calculated. You can specify parameters such as, calculation frequency (weekly, monthly, annually), number of days accrued in a year, number of premium days accrued based on the number of months of employment, etc. This is then attached to a policy group, which is attached to an employee’s contract.  A cron job automatically takes care of calculating and depositing the days into an accrual object integrated with hr.holidays based on the schedule you specify. 

Payroll Management

The modules implementing this functionality are: hr_payroll_extension, hr_payroll_period, hr_policy_absence, hr_policy_ot, hr_payslip_amendment

These relatively few modules implement quite a bit of functionality. They build on top of the basic functionality provided by OpenERP, such as salary rules, payslips and payslip runs, and build a robust payroll management system on top of it. The payroll management is built around the concept of a payroll period schedule. A payroll period schedule defines basic parameters of the payroll such as: the length of the payroll cycle, the day the payroll week starts (i.e. Monday), the time zone in which the attendance records are to be evaluated, and overtime behavior when crossing the midnight boundary. This is attached to the employee’s contract and determines how and when the employee is paid. The current implementation provides a manual cycle and a monthly cycle, but it would take only a trivial amount of work to provide weekly, or semi-monthly cycles. There are cron tasks that will create payroll periods automatically according to the schedules in the system. When the payroll period ends there is an “End of Payroll Period” wizard that takes you through the steps of creating pay slips and paying your employees.

In addition to payroll periods the payroll processing parts have been heavily modified to provide detailed statistics based on an employee’s schedule vs. attendance records. At the same time I have taken some care to decouple functionality that likely varies between implementations from the actual processing itself. For example, the calculation of overtime is largely contained in the the hr_policy_overtime  module, and the calculation of leaves (with respect to payroll) is handled in hr_policy_absence. You can create as many combinations of these policies as necessary in an hr_policy_group  object which is then attached to an employee’s contract.  The hr_payroll_extension module takes care of combining all these different objects to create a timely and accurate payroll.

Miscellaneous Modules

There are other modules that provide various functionality that might be of interest to an HR manager. These include:

  • hr_webcam  – take a picture of the employee from within OpenERP through a webcam
  • hr_infraction – mechanism for handling complaints and taking disciplinary action
  • hr_job_hierarchy – create manager/subordinate relationships based on the job position


There are a couple of patches you will need to get full use out of these modules.  They should actually be bug-reports, but I haven’t had the time yet get it done so they are included in the project. The first patch is to hr_payroll. It fixes a bug and also allows you to use python expressions in the ‘Quantity’ field of salary rules.  The second is a patch that makes the ‘needaction’ counts of objects bubble-up through their parent menus.

So, their you have it.  With a local check-out of the modules and this description you should be able to get started with this system. In the future I would like to include some demo data to make it easier to understand these module, but for the moment there is none.  While I have tried to polish these modules to make them as generic as possible there will undoubtedly be bugs that I failed to anticipate and places where you will encounter behavior specific to my circumstances. Please file bug-reports for these and I’ll try to fix them up in my copious free time. Better yet, include a patch in the bug report. Even better yet fix it in your local branch and send me a merge proposal.

Please give the modules a spin and let me know what you think.


Integrating OpeneRP stock management with your financial accounts

Edit: Added Valuation Account setting

ERP software is notoriously difficult to configure and manage. This is partly a reflection of the relative immaturity of the sector, especially in the Open Source world, and the sheer complexity of designing a system that can scale from a single mom-and-pop store to a multi-company corporation.  There is also the complexity of trying to design a system that is flexible enough to accommodate the myriad different ways companies can structure their internal business processes.  A good ERP system has to be complex enough that it can be used in a wide variety of businesses in a wide variety of business sectors from a wide variety of countries with different business norms and regulatory requirements.  However, since it is incredibly hard, dare I say impossible,  to design such a system that will not require modifications for specific business circumstances it should also be easy to understand, modify, and extend.  OpenERP is an Open Source ERP platform that strikes a good balance between “complex enough to be used in many business circumstances” and “simple enough to hack on.”

Having said that, one of the areas I have had trouble with in OpenERP is having stock movements accurately reflected in the financial accounts.  This includes the entire process from purchase to sale, and all the steps in between like movement between warehouses or from warehouse to production and back to stock as a finished good.  After quite some time of trying to puzzle it out and lots of experimentation I have a better understanding now, and I hope this post can help others out there struggling with this.


The first step is deciding how you want to track your stock.  Do you want to value your stock by category (regardless of which warehouse it’s in), do you want a valuation by warehouse or do you want a combination of both. OpenERP can accommodate any of these choices but you need to decide at the outset so you know which settings to change.

From Purchase to Sale

There are several places in the purchase-stock-sale life-cycle where stock valuations need to be updated:

  1. Purchase
  2. Receipt of purchased goods
  3. Internal Transfer (i.e. – if we manufacture finished goods)
  4. Sale

Financial Accounts

When we make a purchase we don’t want it to automatically be expensed (which is what happens by default). Instead, we need an account in which we will value goods that have been bought, but not delivered yet. We’ll call this account “Goods in Transit.” We will need another account (or multiple accounts) in which we will value goods in stock. This account will be called “Stock.” OpenERP is flexible enough that we can have one account for all stock, multiple accounts based on the product or the product category, multiple accounts based on the location of the stock, or a combination of all of these.  To keep things simple we will simply have one “Stock” account for all our products. Lastly, we need an account to value the cost of goods sold when we actually sell the items.

Here are the financial accounts we will create:

  • Sales of Goods
    • Account No: 110000
    • Internal Type: other
    • User Type: Income
  • Goods in Transit
    • Account No : 230100
    • Internal Type: other
    • User Type: Asset
  • Stock
    • Account No: 230200
    • Internal Type: Other
    • User Type: Asset
  • Cost of Goods Sold
    • Account No: 510100
    • Internal Type:  Other
    • User Type: Expense
Configuring Stock Properties

Your first stop in configuring products properly is  “Product Category” configuration. You will need to enable real-time stock valuation on the product itself and also enable the “Technical Features” access right for your user before you can do this.  You may also have to enable accounting entries generation per stock movement from Settings -> Warehouse -> Accounting. Once you’ve done that refresh the page and open up the “Warehouse” top-level menu. In the configuration sub-menu click “Product Categories.” This will open up the list of product categories.  By default there are only two to begin with. Open the “All Products / Saleable” record.  Edit the following fields:

  • Income Account – “110000 Sales of Goods”
  • Expense Account – “230100 Goods in Transit”
  • Stock Input Account – “230200 Stock”
  • Stock Output Account – “510100 Cost of Goods Sold”
  • Stock Valuation Account – “230200 Stock”

Now, any products you add under the “All Products / Saleable” category (or its children) will automatically be valued in the right financial accounts. That is, when you make a purchase accounting entries will be created in the “Goods in Transit” asset account.  When the shipment is received that balance will be transferred from “Goods in Transit” to “Stock”, and when you sell it the cost price of the goods will be reflected in the “Cost of Goods Sold” expense account.

Advanced Configuration

This configuration will work for simple setups, but how about for more complicated situations. For example, how do you accurately reflect inventory losses? If you also manufacture finished goods how do you value them correctly? This is where valuation accounts on stock locations come in.  If you set the “Stock Valuation Account (Incoming)” and “Stock Valuation Account (Outgoing)” to the appropriate financial accounts OpenERP will automatically create accounting entries when goods enter or leave those stock locations. Note that in OpenERP 7 these fields are only visible in “inventory” and “production” locations.

Bringing It All Together

In OpenERP you can configure stock valuation accounts in three places:

  1. Product
  2. Product Category
  3. Stock Locations (inventory and production)

The order of precedence of these accounts is as follows:

  1. Stock Locations
  2. Product
  3. Product Category

When you receive a product or when you transfer it internally, if the source or destination location has a valuation account(s) configured it will take precedence over any values in the product or product category.  Otherwise, any values configured in the product take precedence over any values configured in the product category.  This system allows you a great deal of flexibility in valuing your products in your financial accounts. But to take advantage of them you need to enable real-time valuation of stock, enable technical features for your user (or the Administrator depending on who is doing the configuration), enable accounting entries per stock movement (Settings -> Warehouse -> Accounting), and enable management of multiple locations (Settings -> Warehouse -> Accounting).

I know it took me a while to understand stock valuation in OpenERP, so I hope my experience can help someone else out there struggling with the same thing.  If I’ve left something out or I’ve misunderstood something please let me know in the comments.