An introduction to ERPNext module development

par Sébastien Morele, mis à jour le 02/03/2016

In our previous article about ERPNext, we had briefly presented the tools with a promise, come back with another one to describe how to develop modules with Frappé, the framework behind the scene. Here it is !

Because this subject is incredibly huge, we do not cover all problematics about module development. Today  we'll focus on basics to produce a minimum viable application.

Like we saw in the post about MeteorJs, we are going to build an application to manage interventions with these prerequisites:

  • The application provides a way to create a user account and to log in
  • The application is available for connected users only
  • It should be possible to add, edit, and delete customers
  • it should be possible to add, edit and delete interventions linked to these customers

Before starting the application development let's review some core concepts :

  • Frappé is a framework which allows creating applications
  • ERPNext is an application built with Frappé
  • Bench is a collection of command line tools to help the developer in his tasks

Starting a new project

First of all, install the bench tools. You'll find all explanations about it in the official documentation.

Once installed, we can start a new project with these commands:

bench init frappe-demo
cd frappe-demo
bench get-app erpnext https://github.com/frappe/erpnext
bench new-site demo
bench install-app erpnext

Some explanations:

  • We initiate the "frappe-demo" project and go into its directory
  • We download the "erpnext" application
  • We start a new website called "demo"
  • Then, we push the downloaded erpnext app onto the website

Now, execute the bench start command and go to localhost:8000 you should see something like this screen

ERPNext desk

 

Great ! We have a working ERPNext instance, we can play with it and start developing our module.

The intervention management application

Let's use again "bench" to start our application. As we saw, the bench is a nice tool which will help in your applications management. Really powerfull you'll find all the documentation you need in the official page.

To create our application (assuming you're still in the frappe-demo folder) execute the command bench new-app {app_name} and follow instructions. The command creates a boilerplate application for you:

$ bench new-app interventions_management
App Title (defaut: Lib Mgt): Interventions Management
App Description:  App for interventions
App Publisher: Anybox
App Email: smorele@anybox.fr
App Icon (default 'octicon octicon-file-directory'): 
App Color (default 'grey'): 
App License (default 'MIT'): 

If you go back to your ERPNext desk screen, there are no changes, it's just because we did not add our application to the website. Then, as we did before with the ERPNext application, add the new application with the command bench install-app interventions_management. Our application is still invisible on the desk but you can search it in the top search bar and you'll find it but at this moment it's a blank page.

Let's add roles and models.

Roles and permissions

Roles are a feature to manage user permissions on models. In our example, we can define two differents roles:

  • Administrator who can create, update, and delete interventions and customers. We'll use the provided Administrator role
  • Technician who can only read interventions and cannot access customers

 To create the technician role, go to Setup > Users > Role > New

Application models

 Models in Frappé are called DocTypes and you can create them directly from the web interface. All Doctypes are made of fields called DocFields.

When you create a DocType a new folder is created in the module and a model JSON file and a controller template in Python are automatically created. When you update the DocType, the JSON model file is updated and whenever bench migrate is executed, it is synced with the database. This makes it easy to propagate schema changes and migrate the database.

To create a new doctype, go to Developer > Documents > Doctype > New from your Desk interface.

This interface allows us to create and manage DocTypes, let's start with the first DocType called intervention.

First of all, the interface asks which module is concerned. In our case it's interventions_management. Then we add fields:

Field name Type Detail
title Data  
detail Text  
author Link Add "user" into options field
priority Select Add values "Low", "Medium", "high" into options field
customer Link Add customer into options field

 

Our intervention is linked to two other models, User which is a core model and Customer, a new one we need to define. In this tutorial context, we juste define a customer with a name even if in the reality we should need more fields to fill adress, phone, and other details.

Field name Type Detail
customer_name Data  

 

By defining these two models, our application is almost done. Seriously ! Save and go to the desk UI.

Because everything is magic, you should see your app beside others.

interventions management app

Change the application behavior with Controllers

Our application is plainly fonctionnal but we can make some improvements. For example, in our intervention model we have defined an author. It would be great if this field was filled automatically with the current user. To do so , we'll use a controller. A controller is a Python class which manages actions on models through differents events:

  • before_insert
  • validate (before inserting or updating)
  • on_update (after saving)
  • on_submit (when document is set as submitted)
  • on_cancel
  • on_trash (before it is about to be deleted)

In the case of the intervention DocType, the controller is apps/interventions_management/interventions_management/interventions_management/doctype/intervention/intervention.py

Take a minute to read this piece of code and understand what it does:

# -*- coding: utf-8 -*-
# Copyright (c) 2015, Anybox and contributors
# For license information, please see license.txt

from __future__ import unicode_literals
import frappe
from frappe.model.document import Document

class intervention(Document):

    def validate(self):
        if frappe.session.user:
            self.author = frappe.session.user
        else:
            frappe.throw(_("Intervention needs an author"))

Some explanations. Our class inherits the Document class, then we can access our record via self. Frappé comes with builtin methods to get session data or for example raise an exception and we use them to set the author or inform user if there are no sessions. Simple isn't it ?

And finally let the magic operate

Until now, we only focus on models and controllers. We never wrote a line for the presentation layer but you can currently enter some records from the desk interface. It's possible thanks to the framework which builds the interface with models and permission definitions. Then because our DocField have properties and our user too, Frappé knows exactly what data to present and how.

 

This introduction to module development is now finished. We have discovered how to create applications fastly and easily. There is so much to say about Frappé and ERPNext, we cannot concat all subjects in an unique blog post. Feel free to contact us to talk about or if you need us to get into a specific point, otherwise see you in a future post !

Contenus corrélés