Skip to content
Service · Asset management module

An asset management system that finance and the workshop both believe

In most companies the fixed asset register belongs to finance and the maintenance log belongs to whoever runs the workshop. They describe the same machines and rarely agree. An asset management system inside ERPNext or Odoo puts depreciation, location, meter readings and repairs on one record. Tell erpfly how your equipment is used and serviced, and it writes the module.

ERPNext v16

Works with ERPNext v15 and v16, and Odoo 17, 18 and 19.

Features

What your asset management module can do

One record, two audiences

The asset carries purchase value, depreciation and book value for finance, and serial number, location and service history for the workshop.

Service by hours, not only by date

Hour or kilometre meters drive preventive maintenance, because a generator that ran 900 hours last month needs service sooner than one that sat in the yard.

Readings that can't go backwards

A meter reading lower than the last service is rejected with a message. Fat-finger errors stop creating phantom overdue services.

Repairs that hit the books properly

Routine fixes post as expense. Larger ones that extend useful life get capitalised and the depreciation schedule recalculates.

Know where things physically are

Asset movements between sites, custodians and customer hires are logged, so the annual stock take isn't a search party.

The output

What actually gets generated

Real files in a real repository. Here’s the typical output when someone asks for asset management.

ERPNext / Frappe app

  • Custom fields on Asset (running hours, service interval)
  • Meter Reading DocType linked to Asset
  • Asset Maintenance tasks raised from meter readings
  • Asset Repair capitalisation rule by threshold
  • Asset register Script Report grouped by location

Odoo addon

  • maintenance.equipment inheritance with hour meters
  • ir.cron creating preventive maintenance.request records
  • Link to account.asset on Enterprise, or OCA account_asset_management on Community
  • Meter reading model with list and graph views
  • ir.model.access.csv rules for technicians and finance
plant_hire_assets/models/maintenance_equipment.py
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError

class MaintenanceEquipment(models.Model):
    _inherit = "maintenance.equipment"

    running_hours = fields.Float(tracking=True)
    service_interval_hours = fields.Float(default=250.0)
    last_service_hours = fields.Float()
    hours_to_service = fields.Float(compute="_compute_hours_to_service", store=True)

    @api.depends("running_hours", "last_service_hours", "service_interval_hours")
    def _compute_hours_to_service(self):
        for eq in self:
            eq.hours_to_service = eq.last_service_hours + eq.service_interval_hours - eq.running_hours

    @api.constrains("running_hours", "last_service_hours")
    def _check_meter(self):
        for eq in self:
            if eq.running_hours < eq.last_service_hours:
                raise ValidationError(_("%s: the hour meter can't be below the last service reading.", eq.name))

    @api.model
    def _cron_raise_meter_services(self):
        for eq in self.search([("hours_to_service", "<=", 0), ("scrap_date", "=", False)]):
            if eq.maintenance_ids.filtered(
                    lambda r: r.maintenance_type == "preventive" and not r.stage_id.done):
                continue  # one open preventive request is enough
            self.env["maintenance.request"].create({
                "name": _("%s hour service", int(eq.service_interval_hours)),
                "equipment_id": eq.id,
                "maintenance_type": "preventive",
                "schedule_date": fields.Datetime.now(),
            })
Trimmed excerpt. The full module includes tests, fixtures and a README.

How it works

From a paragraph to a pull request

The long version
  1. 01

    Describe it

    In your own words. Paste the spreadsheet or a photo of the paper form if that's easier.

  2. 02

    Answer a couple of questions

    It asks only what it can't work out from your setup, like who's allowed to override.

  3. 03

    Try it on a sandbox

    A copy of your site with the module installed. Break it, then ask for changes.

  4. 04

    Merge when it's right

    Code lands as a pull request with tests. Your developer, or ours, reviews it first.

Why an asset management system needs one record, not two

Ask finance how many generators the company owns and you’ll get a number from the fixed asset register. Ask the workshop and you’ll get a different number, from a spreadsheet or a whiteboard. Both are sort of right. One includes the unit that was written off but still gets used for spares. The other includes the unit bought on a credit card and never capitalised.

That gap is what an asset management system should close. It isn’t about fancier depreciation. It’s about both teams looking at the same record and trusting it.

What ERPNext and Odoo give you before any custom code

ERPNext is strong here out of the box. The Asset DocType handles purchase, depreciation (straight line, written down value, double declining balance or manual) and disposal, with Asset Category holding accounts and defaults. Newer versions keep schedules in a separate Asset Depreciation Schedule. Asset Movement, Asset Repair, Asset Value Adjustment and Asset Maintenance cover most of what the workshop does.

Odoo splits the job by edition. Depreciation lives in account.asset, which is Enterprise. The Maintenance app, with maintenance.equipment and maintenance.request, is in Community. Linking the two is left to you.

So the gaps are specific. Meter-based servicing isn’t really there on either platform. Linking equipment to the financial asset on Odoo takes work. And capitalisation rules are your accountant’s opinion, not a platform default.

What erpfly adds sits in its own app or addon. On ERPNext that means a Frappe app with a Meter Reading DocType, custom fields on Asset shipped as fixtures, and hooks that raise Asset Maintenance tasks when a reading crosses the interval. On Odoo it’s an addon that inherits the equipment model, adds a scheduled action through ir.cron, and extends the stock form and list views instead of replacing them. Access rules are written out explicitly, because technicians should be able to log a reading without seeing what the machine cost.

None of this edits core files. When you move to the next major version, your register and your service history come along, and the tests tell you if a field you rely on has been renamed.

Worked example: plant hire with hour meters

Picture a hire company with around 60 generators and compact excavators, operating from two depots.

A new 100 kVA generator costs $18,000. Salvage value is $3,000 and useful life 5 years, straight line. That’s $15,000 over 60 months, or $250 of depreciation a month, and it posts without anyone touching it.

Service is due every 250 running hours. When the unit returns from a hire, the yard hand reads the meter and enters 1,142. The last service was at 890. That’s 252 hours since service, so the scheduled job raises a preventive maintenance request that night. Busy units on long hires run about 70 hours a week, which puts them in the workshop roughly every three and a half weeks.

In month 14 the alternator fails. The repair costs $1,650, above the company’s $1,000 threshold, and the workshop manager records that it extends the unit’s life by a year. It’s capitalised, and the remaining depreciation is spread across the new remaining life. A $300 fuel pump swap the week after just posts as an expense.

One record holds all of it. Finance sees book value. The workshop sees hours to next service.

Where we’d push back on scope

Some asset projects try to track everything, and they end up tracking nothing well.

Don’t register $40 office chairs as individual assets. Set a capitalisation threshold with your accountant and expense everything below it.

Don’t start with live sensor feeds. Manual readings for a month will show you which meters are broken, which staff skip the reading, and whether the intervals make sense.

And don’t write your own depreciation engine. Both ERPNext and the Odoo asset modules handle the maths, including the awkward mid-year disposals. Build the rules around them, not a replacement.

Where assets meet the rest of the ERP

Vehicles are assets with extra paperwork, so the fleet management module shares a lot with this one. Depreciation and capitalised repairs land in your accounting ledgers. Production equipment ties into manufacturing workstations, and our page for manufacturers covers downtime tracking in more detail.

On Odoo and planning to link Maintenance to Enterprise assets? Odoo module development explains how we structure the addon.

Guides and terms for asset management

Asset management module questions

Something missing? Email hello@erpfly.com and a person will answer.

Is asset depreciation included in Odoo Community?

No. The Assets feature (account.asset) is part of Odoo Enterprise Accounting. On Community, the OCA account_asset_management addon is the usual route, and we can generate against it. Maintenance itself is in Community.

Can we import our existing fixed asset register?

Yes. We generate an import that creates each asset with its original cost, purchase date and accumulated depreciation to date, so book values match your last audited numbers. Expect a reconciliation pass with your accountant before go-live.

Can meter readings come from telematics or IoT sensors?

They can, through a scheduled job that calls the device vendor's API and writes readings. We'd start with manual readings for a month first. You'll learn which machines report garbage before you automate the garbage.

Does it handle separate tax and book depreciation?

ERPNext supports multiple Finance Books per asset, so tax and book schedules can run side by side on standard features. On Odoo it depends on which asset module you run. We'd use what the platform already does rather than write depreciation maths from scratch.

Can technicians log readings on a phone in the yard?

Yes, through a small mobile-friendly form that takes the asset, the reading and an optional photo. It needs a connection when you hit save, which is rarely a problem in a yard.

Your next module is one paragraph away

Write it the way you’d explain it to a new hire. We’ll turn it into an app you can read, test and install.

ERPNext v16