Welcome to the koalixcrm
Why koalixcrm
| Values: | Features: |
|---|---|
|
|
Quality badges on master
| Project build: | Codacy results: | Docker: | Social Networks: |
|---|---|---|---|
![]() |
Documentation
You can find the documentation of koalixcrm here: doc
Installation
Some information about the installation of koalixcrm: installation
Getting started
The stack is orchestrated from the sibling repo
koalixcrm_system
(docker-compose + infra config). Pick the guide that matches your
environment:
- Local setup with Docker Desktop — Windows / macOS / Linux workstation
- Linux server install (VPS / VPC) — headless Linux host with native Docker
Both guides cover launching the app and picking the UI language
(en-us, de, fr, es, pt-br via the KOALIXCRM_LANGUAGE_CODE
env var). Admin/user configuration is covered separately in the
configuration guide (coming soon).
Release Process
This fork uses a Git Flow workflow: all development integrates through develop, and only
stabilized releases are promoted to main. (Upstream's original notes:
scaphilo/koalixcrm wiki — Release Process.)
Branches
main— production. Every commit onmainis a release, taggedvX.Y.Z.develop— integration branch.feature/*— short-lived, branched fromdevelop.release/*— short-lived stabilization branch, branched fromdevelop.hotfix/*— urgent fix branched frommain, merged back to bothmainanddevelop.
Visual overview
Every release on main is back-merged into develop, so the two branches never diverge. The
same back-merge happens for hotfixes — whatever lands on main flows back to develop.
gitGraph
commit id: "v2.9.0" tag: "v2.9.0"
branch develop
checkout develop
commit id: "dev work"
branch feature/QUAQ2-123
checkout feature/QUAQ2-123
commit id: "feature work"
checkout develop
merge feature/QUAQ2-123 id: "squash"
commit id: "more dev work"
branch release/2.10.0
checkout release/2.10.0
commit id: "bump + stabilize"
checkout main
merge release/2.10.0 tag: "v2.10.0"
checkout develop
merge release/2.10.0 id: "back-merge release"
checkout main
branch hotfix/2.10.1
checkout hotfix/2.10.1
commit id: "urgent fix"
checkout main
merge hotfix/2.10.1 tag: "v2.10.1"
checkout develop
merge hotfix/2.10.1 id: "back-merge hotfix"
The
feature/* → developarrow is a squash merge; every arrow intomainand the two back-merges intodevelopare real merge commits (--no-ff).
The one rule that keeps main and develop healthy
Squash only when merging feature/* → develop. Use real merge commits (--no-ff, never squash) for release/* → main and the back-merge release/* → develop.
A squash merge creates a commit that is not a descendant of the source branch's commits, so two long-lived branches lose their shared ancestor and every later release re-lists the entire history ("huge diff"). Real merges preserve ancestry, so each release diff shows only what is new.
Day-to-day: feature → develop
git switch develop && git pull
git switch -c feature/QUAQ2-123-short-title
# ...work...
# open PR feature/... -> develop, merge with "Squash and merge"
Cutting a release (develop → main)
git switch develop && git pull
git switch -c release/2.10.0
# bump version, update changelog, last stabilization fixes only
git push -u origin release/2.10.0
# 1) PR release/2.10.0 -> main, merge with "Create a merge commit" (NEVER squash)
# 2) tag main:
git switch main && git pull
git tag -a v2.10.0 -m "Release 2.10.0"
git push origin v2.10.0
# 3) back-merge so develop gets the version bump / stabilization fixes:
# PR release/2.10.0 -> develop, merge with "Create a merge commit"
The back-merge is now small (only the release-branch commits), not a repair of divergence.
Hotfix (main → main + develop)
git switch main && git pull
git switch -c hotfix/2.10.1
# fix the bug, bump patch version
git push -u origin hotfix/2.10.1
# 1) PR hotfix/2.10.1 -> main, merge with "Create a merge commit" (NEVER squash)
# 2) tag main:
git switch main && git pull
git tag -a v2.10.1 -m "Hotfix 2.10.1"
git push origin v2.10.1
# 3) back-merge so develop also gets the fix:
# PR hotfix/2.10.1 -> develop, merge with "Create a merge commit"
Skipping the back-merge is the usual cause of main and develop drifting apart — the fix would
otherwise live only on main and get re-introduced as a "regression" on the next release.
Reading history
git config log.first-parent true # add --global for all repos
git log --oneline --first-parent main # one line per release, ancestry preserved
GitHub repo settings
Enable both merge styles and use them by convention:
- Allow squash merging → feature/* → develop
- Allow merge commits → release/* → main, hotfix/*, and back-merges
Django migrations
- Parallel features that each add a migration off the same parent collide. Resolve on
developwithpython manage.py makemigrations --merge, or rebase the feature branch so it renumbers. - Run
python manage.py makemigrations --check --dry-runbefore merging to catch unmerged or missing migrations. squashmigrations(and full migration resets) are RARE, DELIBERATE maintenance — not a per-release step. Only when migration count hurts test/setup time, and only when all environments are caught up. Keep originals until every environment is past them, and reconcile existing databases withmigrate --fake-initial. For this fork's upgrade/data-migration specifics, see Upgrade from 1.14.0 to v2.0.0 and Migration utilities reference below.
FAQ
The release merge commit on main carries the version bump / migration — how do I get the same thing onto develop? Do I have to merge main → develop or cherry-pick?
No. A merge commit is defined by its parents, so the commit on main can't be replayed onto develop — but you don't need it. The version bump and migration are committed on the release/* (or hotfix/*) branch, never directly on main. You then merge that same branch into both targets:
release/2.10.0 ──┬──> main (merge commit A, tagged v2.10.0)
└──> develop (merge commit B, the back-merge)
A and B are two different merge commits, but both pull in the same release-branch commits — so develop gets the migration via its own back-merge, not by copying A. Cherry-pick or main → develop only become necessary if something was committed straight onto main, bypassing a release/hotfix branch — which is exactly the anti-pattern this process avoids.
GitHub gotcha: don't delete the
release/*/hotfix/*branch after the first PR. Keep it until the back-merge PR (→ develop) is merged — otherwise you lose the branch you needed to merge from, which is the usual reason people fall back tomain → develop.
Where do I tag — on main or on the release branch?
On main, on the merge commit, after the merge. main is production ("every commit on main is a release"), and tags vX.Y.Z mark releases on main, so git log --first-parent main gives one tagged line per release. The release branch is short-lived and deleted, so a tag there would dangle. Tag after merging so the tag lands on the real production state (the merge commit), not on a pre-merge release commit. Same for hotfixes: merge hotfix/* → main, then tag the resulting merge commit.
# after PR release/2.10.0 -> main is merged:
git switch main && git pull
git tag -a v2.10.0 -m "Release 2.10.0" # tags the merge commit on main
git push origin v2.10.0
Upgrade from 1.14.0 to v2.0.0
v2.0.0 is a major release that restructures the monolithic crm app into independent Django apps:
| New app | Moved from | Contains |
|---|---|---|
accounting |
accounting (unchanged) |
Account, AccountingPeriod, Booking, ProductCategory |
contract_object_management |
crm |
Contract, SalesDocument, Invoice, Quote, DeliveryNote, Position, ... |
products |
crm |
Currency, ProductType, Product, Tax, Unit, Price, ... |
reporting |
crm |
Project, Task, Work, ReportingPeriod, Agreement, Estimation, Resource, ... |
crm |
crm (reduced) |
Contact, Customer, Supplier, Person, Call, EmailAddress, PhoneAddress, PostalAddress, ... |
djangoUserExtension |
djangoUserExtension (unchanged) |
DocumentTemplate, TemplateSet, UserExtension, ... |
subscriptions |
subscriptions (unchanged) |
Subscription, SubscriptionEvent, SubscriptionType |
All database table names remain unchanged (crm_* prefix) to preserve data compatibility.
Migration steps (PostgreSQL dump to v2.0.0)
The upgrade requires three steps. Make sure you have a backup of your database before starting.
Prerequisites:
- A PostgreSQL dump from 1.14.0 (e.g. auftraegekoalixnet_20230101.sql)
- The v2.0.0 codebase checked out
- Python virtualenv activated
Step 1 -- Convert PostgreSQL dump to SQLite:
python koalixcrm_utils/pg2sqlite.py your_dump.sql projectsettings/db.sqlite3
Step 2 -- Extract legacy data and prepare for migration:
python koalixcrm_utils/pre_migrate_cleanup.py
This detects the legacy database, extracts all data to projectsettings/legacy_data.json,
and drops all tables so Django can recreate them with proper schemas.
Step 3 -- Run Django migrations to create the new schema:
python manage.py migrate --settings=projectsettings.settings.development_docker_sqlite_settings
Step 4 -- Import legacy data into the new schema:
python koalixcrm_utils/pre_migrate_cleanup.py projectsettings/db.sqlite3 projectsettings/legacy_data.json import
This imports all data back, automatically handling:
- Columns removed in v2.0.0 (e.g. originalAmount in Account) are skipped
- Tables Django manages itself (django_migrations, auth_permission, django_content_type) are skipped
- Foreign key relationships are preserved (all tables keep their original crm_* names)
Fresh install (no existing data)
For a fresh v2.0.0 install without existing data, simply run:
python manage.py migrate --settings=projectsettings.settings.development_docker_sqlite_settings
python manage.py createsuperuser --settings=projectsettings.settings.development_docker_sqlite_settings
Migration utilities reference
| File | Purpose |
|---|---|
koalixcrm_utils/pg2sqlite.py |
Converts a PostgreSQL dump file to SQLite3 |
koalixcrm_utils/pre_migrate_cleanup.py |
Handles legacy data extraction, table cleanup, and data re-import |
koalixcrm/migration_utils.py |
CreateModelIfNotExists and AddFieldIfNotExists -- migration operations that skip table/column creation when they already exist, allowing the same migrations to work for both fresh installs and upgrades |
Update from version 1.12 to 1.14
Some information about the update procedure from Version 1.12 to Version 1.14: update
