Skip to content

Extending an existing module

The first walkthrough builds a module from nothing. This one does the other half of the job, and it is the half you will do most often: a module already exists, it almost does what you need, and you are three fields and one rule short.

The wrong answer is to copy it and edit the copy. The day its next version ships, you have two codebases to reconcile and nobody to do it.

What we are going to build

pipeline is the deals module: leads, stages, forecasts. It knows nothing about the competition, which is the first question of any pipeline review: who were we up against, and who won?

We add a pipeline_rivals module that:

  • brings its own model, rivals_competitor;
  • adds two fields to pipeline_lead, without touching pipeline’s code;
  • completes pipeline’s screens instead of replacing them;
  • reacts to what happens in pipeline without ever importing it.

At the end, a deal’s form carries “Up against” and “Lost to”, the list carries one more column, and pipeline has not changed by a line.

The rule that holds it all together

A business module never imports another business module. That is interdiction no. 8 in CLAUDE.md, and it is not a style preference: an import modules.pipeline ties you to its internal functions, which nobody promised to keep. You depend on it, it does not know, and its next version breaks you.

What you do name are public facts:

You nameYou do not name
a model (pipeline_lead)the Python module behind it
a field (state, source_id)the function computing it
an event (record.updated)the line emitting it
a group code (pipeline_manager)the group object

Everything else in this walkthrough follows from that.

What you need at hand

An instance with pipeline installed and activated, and at least a skim of the first walkthrough: what a model, a view or a translation file is does not get explained again here.

The steps

1The extension moduleThe manifest, the dependency, and what we do not write.
2Adding fieldsContributing to a model that is not yours.
3Completing a screenA patch, not a replacement.
4Reacting, and leavingListening without importing, and uninstalling cleanly.