Member & subscription management system for our cooperative WirGarten Lüneburg e.G.
  • Python 70.7%
  • TypeScript 18.1%
  • HTML 6%
  • CSS 3.3%
  • Fluent 1%
  • Other 0.8%
Find a file
2026-04-15 16:32:21 +02:00
.github/workflows chore: removed the explicit CodeQL action as it is now handle from GitHub direclty without workflow file. 2026-04-02 11:46:33 +02:00
.vite/deps Merge branch 'refs/heads/biotop-dev' 2026-04-01 16:48:21 +02:00
dist fix: keep the dist folder in the repo to avoid a warning on docker compose up -d 2026-04-02 12:10:22 +02:00
docker/keycloak chore: removed unused nginx files. Added all django migrations to files excluded by SonarQube. Misc recommendations from SonarQube implemented. 2026-04-01 17:46:37 +02:00
example_data Integrate tapir-mail in wirgarten tapir (#409) 2024-08-27 19:02:29 +02:00
scripts misc: Added a prettier plugin so that it also organizes imports (#1079) 2026-04-08 11:49:47 +02:00
src_frontend misc: capitalized text to fit other buttons 2026-04-15 12:49:21 +02:00
tapir fix: when generating test subscriptions, set the subscription creation dates to their start date so that the payments are realistic. 2026-04-15 12:46:44 +02:00
.gitattributes Use hash to avoid changes in generated API classes and auto-format generated files with prettier (#1077) 2026-04-08 10:45:42 +02:00
.gitignore misc: Added a prettier plugin so that it also organizes imports (#1079) 2026-04-08 11:49:47 +02:00
.pre-commit-config.yaml dev: replaced the formatter for HTML templates from djlint to djhtml (#1088) 2026-04-14 13:54:54 +02:00
.prettierrc.json misc: Added a prettier plugin so that it also organizes imports (#1079) 2026-04-08 11:49:47 +02:00
.schema.hash fix: #1093 used POST data instead of GET parameters for subscriptions:confirm_subscription_changes because the URL gets too long when trying to confirm many entries. 2026-04-13 15:56:45 +02:00
.sonarcloud.properties Added a config file for SonarCloud. 2022-02-21 19:59:10 +01:00
CONTRIBUTING.md #5: Require Pipeline before PR Merge (#8) 2022-09-21 12:26:11 +02:00
docker-compose.yml dev: use a solo pool for celery like the prod containers. 2026-04-15 16:32:21 +02:00
Dockerfile Revert "chore: updated the dockerfile so that dev dependencies are not installed on prod images." 2026-04-14 09:35:05 +02:00
LICENSE Added LICENSE file (AGPLv3) 2025-07-31 16:52:23 +02:00
Makefile tests: Keycloak is now mocked on all integration tests. (#1064) 2026-04-02 09:51:00 +02:00
manage.py misc: fixed black formatting for new version 2026-01-27 12:28:38 +01:00
models.png chore: updated the model graph. 2026-04-10 09:54:01 +02:00
openapitools.json Added a Vite docker container that runs NPM and vite. Configured vite to allow React in django templates. 2025-03-06 10:56:09 +01:00
package.json fix: updated react-dom to fit the version for react 2026-04-09 14:25:40 +02:00
pnpm-lock.yaml fix: updated react-dom to fit the version for react 2026-04-09 14:25:40 +02:00
poetry.lock dev: replaced the formatter for HTML templates from djlint to djhtml (#1088) 2026-04-14 13:54:54 +02:00
pyproject.toml dev: replaced the formatter for HTML templates from djlint to djhtml (#1088) 2026-04-14 13:54:54 +02:00
README.md dev: replaced the formatter for HTML templates from djlint to djhtml (#1088) 2026-04-14 13:54:54 +02:00
schema.yml fix: #1093 used POST data instead of GET parameters for subscriptions:confirm_subscription_changes because the URL gets too long when trying to confirm many entries. 2026-04-13 15:56:45 +02:00
sonar-project.properties chore: added the email base template to the sonar cloud exclusions: it's a generated from MJML (I think) and is just too big and complex to make it respect any standard. 2026-04-02 11:45:44 +02:00
tsconfig.app.json feat: in the bestellwizard, product types with only 2 products are shown on the same page instead of inside a carousel 2026-01-07 13:23:26 +01:00
tsconfig.app.tsbuildinfo fix: #1093 used POST data instead of GET parameters for subscriptions:confirm_subscription_changes because the URL gets too long when trying to confirm many entries. 2026-04-13 15:56:45 +02:00
tsconfig.json feat: in the bestellwizard, product types with only 2 products are shown on the same page instead of inside a carousel 2026-01-07 13:23:26 +01:00
tsconfig.node.json US 5.8 #742: More modern ts version in tsconfig. 2025-12-19 16:49:35 +01:00
tsconfig.node.tsbuildinfo chore: pnpm dependency updates. 2026-04-09 14:13:34 +02:00
vite.config.ts chore: removed many React files that used by the old order wizard, also removed the corresponding django views. 2026-04-09 14:01:16 +02:00
vite.Dockerfile fix: Docker/Vite development setup (#1022) 2026-03-29 12:05:41 +02:00

Tapir

Python code test coverage

Tapir is a management system for community supported agriculture. It is currently used productively by several organizations, including WirGarten Lüneburg eG, Möllers Morgen, Gemüsekollektiv Hebenshausen e.V., and more.

Its features include:

  • Member & membership management including cooperative shares
  • Contract management: yearly commitment, weekly deliveries, solidarity contributions, renewal...
  • Communication with the members with customizable automated mails
  • Delivery locations and capacity management
  • And more

It is developed by Théo for FoodCoopX.

The backend code is written with Python and Django, the frontend code is a mix of Django templates and React.

Don't hesitate to contact us if you are interested in using or contributing to Tapir.

Getting started

Use docker to quickly get a development server running on your machine. Run the following commands:

docker compose up -d
# Create tables
docker compose exec web poetry run python manage.py migrate
# Define the configuration parameters
docker compose exec web poetry run python manage.py parameter_definitions    
# Generate test data
docker compose exec web poetry run python manage.py populate --reset_all

You should now have a local instance accessible at http://localhost:8000/. You can log in as admin with username roberto.cortes@example.com and password roberto.cortes.

You can log in as any user using the same pattern: [name]@example.come as username and [name] as password

Tests

Tests are run with pytest:

docker compose exec web poetry run pytest --reuse-db -n auto

If you run into troubles while running the tests, try running them without --reuse-db -n auto.

You can run unit tests outside the Docker container with just by simple running pytest, assuming you have the poetry environment installed and activated. That should be a bit faster. Integration tests must be run from inside Docker.

Keycloak during tests

User authentication is handled by keycloak through django-allauth. During integration tests, this connection is mocked via tapir.wirgarten.tests.test_utils.mock_keycloak, called in TapirIntegrationTest. The mocking happen during setUp and setUpTestData happens before setUp, that means we can't create users inside setUpTestData.

Formatting

Python files are formatted with Black.

JavaScript and React files are formatted with Prettier.

Django template files are formatted with DjHTML

Frontend API clients

API Requests made from the React frontend use API clients. Here are the steps to get updated API clients:

  • Annotate your API view with Spectacular (search for @extend_schema( for examples)
  • Generate the API schema file with python ./manage.py spectacular --file schema.yml
  • Generate the TypeScript API clients using OpenAPI Generator with ./scripts/generate_api_clients.sh

There are help scripts in the /scripts folder. You can do a full update with the following command:

docker compose exec web ./scripts/generate_api_schema.sh && docker compose exec vite ./scripts/generate_api_clients.sh

Style and conventions

Models

Models should inherit from tapir.core.models.TapirModel:

  • It uses nanoid instead of integer IDs, that makes sure we never use an ID from a model when getting another model, for example in tests.
  • It has created_at and updated_at fields that help unterstand the state of production databases.

As much as possible, model classes should contain only their own fields. Helper methods are OK if they only reference the fields of the given object.

Cache

Many functions, especially service functions, take a cache parameter which is a normal python dictionary. The goal of this cache is to avoid redundant database requests within one http request: in most of our views, DB requests are the most time-consuming part. The cache dictionary should be created at the origin point: for example in the view's __init__ function or the first lines or the command. Since this cache only lives for the duration of the request, in most cases it is not necessary to invalidate it. If you do need to invalidate, look at tapir.utils.services.tapir_cache_manager.TapirCacheManager Some functions have the cache parameter optional. This is only because they are called in legacy code, all new functions should have the cache parameter required if possible. For examples, see usages of tapir.utils.services.tapir_cache.TapirCache.

Service classes

Most of the business logic code should be in service classes. You can find examples in tapir/*/services/.

Commits

Use conventional commits for your commit messages. When applicable, add the ID of the related GitHub issue in the commit message.

Legacy code

Everything that is under tapir/wirgarten should be considered legacy code. It doesn't respect the conventions above. If you need to change anything in there, consider rewriting the part that you are changing and moving it to one of the other apps.

Class diagram

models.png

If this graph is outdated, you can re-generate it with:

docker compose exec web sh -c "apt update && apt install -y graphviz graphviz-dev && poetry run pip install pygraphviz && poetry run python manage.py graph_models -a -g -o models.png"

The other Tapir

This Tapir started as a fork of another project: Tapir for cooperative supermarkets. They are now completely separate but have kept the same name. Sorry for the confusion!