New
Apps 1,321Makers 1,319This week 1,321
Promote your app−30%
1views in
the last 30 days

Re-Sharing

A platform for sharing and booking resources efficiently.

Built with Claude Code

by haus-des-engagements · Unclaimed · from DEGermany · added Oct 29, 2026
no ratings0 comments

Re(source)-Sharing

A comprehensive platform for organizations to share and book resources efficiently.

License: GPLv3

Overview

Re(source)-Sharing is a Django-based web application designed to facilitate resource sharing between organizations. The platform allows organizations to list their resources (such as rooms, equipment, vehicles, etc.) and make them available for booking by other organizations, with customizable restrictions, compensation options, and scheduling capabilities.

Key Features

  • Resource Management: Create, update, and manage various types of resources with detailed descriptions and images
  • Organization Management: Register and manage organizations with different activity areas and legal forms
  • Booking System: Book resources with one-time or recurring schedules
  • Compensation Options: Set up different compensation models for resource usage
  • Access Control: Define who can access resources and when
  • Restriction Management: Set restrictions on resource availability based on time or organization
  • User Management: Manage users with different roles and permissions within organizations
  • Email Notifications: Automated email notifications for booking confirmations, cancellations, etc.

Project Structure

The project is organized into several Django apps:

  • users: User management and authentication
  • resources: Resource definition, restrictions, and compensation models
  • organizations: Organization management, permissions, and communication
  • bookings: Booking management, scheduling, and messaging

Installation and Setup

Prerequisites

  • Python 3.12+
  • uv (package manager)
  • PostgreSQL
  • Git

Local Development Setup

  1. Clone the repository:

    git clone https://github.com/Haus-des-Engagements/re-sharing.git
    cd re-sharing
    
  2. Install uv (if not already installed):

    curl -LsSf https://astral.sh/uv/install.sh | sh
    
  3. Install dependencies (uv will automatically create a virtual environment):

    uv sync --extra dev
    export DJANGO_READ_DOT_ENV_FILE=true
    
  4. Set up the database:

    createdb re-sharing
    uv run python manage.py migrate
    
  5. Create a superuser:

    uv run python manage.py createsuperuser
    
  6. Run the development server:

    uv run python manage.py runserver 0.0.0.0:8000
    

For more detailed setup instructions, see: https://cookiecutter-django.readthedocs.io/en/latest/developing-locally.html

Settings

For information about settings configuration, see: https://cookiecutter-django.readthedocs.io/en/latest/settings.html

Two-factor authentication

Variable Default Meaning
REQUIRE_STAFF_MFA True Staff, superusers and managers must set up two-factor authentication (authenticator app or passkey) before using the site. Set to False to switch off, e.g. locally. If a manager loses their device and recovery codes, delete their authenticator in the admin so they can set it up again.

Agreements and SEPA direct debit

Variable Default Meaning
SEPA_CREDITOR_ID empty Creditor identifier printed in pre-notifications and the SEPA file
SEPA_CREDITOR_NAME empty Creditor name in the SEPA file and on the generated mandate
SEPA_CREDITOR_ADDRESS empty Creditor address in one line, printed on the generated mandate
SEPA_CREDITOR_IBAN / SEPA_CREDITOR_BIC empty Account the debits are collected to
SEPA_MANDATE_PREFIX RS Prefix of collection references; also marks bank transactions as possible returns
SEPA_MANDATE_REFERENCE_PREFIX <SEPA_MANDATE_PREFIX>-VM Prefix of mandate references, followed by a running number: HDE-VM-009 continues after the highest existing HDE-VM number, so enter old paper mandates in the admin with their references first
SEPA_RETURN_FEE 0.00 Fee added to the invoice for a returned debit
PRE_NOTIFICATION_DAYS 14 Days between pre-notification and due date
COLLECTION_LOOKAHEAD_DAYS 45 How far ahead collections are created
COLLECTION_RETURN_WINDOW_DAYS 7 Days after the collection date until a debit counts as collected

Basic Commands

Setting Up Your Users

*To create a normal user account, just go to Sign Up and fill out the form. Once you submit it, you'll see a "Verify Your E-mail Address" page. Go to your console to see a simulated email verification message. Copy the link into your browser. Now the user's email should be verified and ready to go.

  • To create a superuser account: uv run python manage.py createsuperuser For convenience, you can keep your normal user logged in on Chrome and your superuser logged in on Firefox (or similar), so that you can see how the site behaves for both kinds of users.

Migrations

After you've made changes in a model, you have to propagate your changes to the database:

  • Create new migrations: uv run python manage.py makemigrations [app_label]
  • Apply migrations: uv run python manage.py migrate [app_label]

[app_label] is optional.

Adding new apps

Our code is organised in so-called "apps", where we try to isolate functionalities and contexts:

Currently, we have the following apps:

  • users
  • bookings
  • resources
  • organizations

To create a new app, first create the new folder, then run: django-admin startapp newappname ./re-sharing/newappname.

Translations

To make strings available for translations in Django:

  1. Make gettext_lazy available as _: from django.utils.translation import gettext_lazy as _
  2. Mark strings as translatable: _('string to be translated)
  3. Run uv run python manage.py makemessages -l de (for German in this case)
  4. Translate the strings now available in /locale/de/LC_MESSAGES/django.po
  5. Compile the .po file with uv run python manage.py compilemessages to a .mo file

Python packages

Dependencies are managed using uv and defined in pyproject.toml.

Adding or updating packages:

# Add a new dependency
uv add package-name

# Add a dev dependency
uv add --dev package-name

# Update all dependencies
uv lock --upgrade

# Sync dependencies after changes
uv sync --extra dev

The uv.lock file tracks exact versions and should be committed to version control.

Database

Postgres

Django connects to a Postgres Database. For local development a Postgres 16 container is defined in docker-compose.yml (listening on port 5433 to avoid clashing with other local instances, data kept in a named volume):

docker compose up -d        # start (data persists across restarts)
docker compose down         # stop, keep data
docker compose down -v      # stop and delete all data

Point Django at it with a .env file (read when DJANGO_READ_DOT_ENV_FILE=true):

DATABASE_URL=postgres://postgres:password@localhost:5433/re_sharing

To (re)create the database from a dump:

docker compose exec -T postgres pg_restore -U postgres -d re_sharing \
    --clean --if-exists --no-owner --no-privileges < ~/Downloads/<dump>.dmp
uv run python manage.py migrate   # apply migrations newer than the dump

Alternatively, without Docker, use a native Postgres and createdb re_sharing, then run pg_restore / migrate against it in the same way.

Linting & Coding Style with Ruff

Before committing we locally verify the correct coding style with different tools. Ruff is a Python linter and code formatter, written in Rust. It is a aggregation of flake8, pylint, pyupgrade and many more.

Ruff comes with a linter uv run ruff check and a formatter uv run ruff format. The linter is a wrapper around flake8, pylint, and other linters, and the formatter is a wrapper around black, isort, and other formatters.

Hint: You can also use an installed pre-commit hook with uv run pre-commit run --all-files, included:

  • UV lock file sync
  • Trim Trailing Whitespaces
  • Fix end of files
  • check Yaml
  • Ruff linting and formatting
  • djLint (indent html templates that contain django syntax correctly)

Testing

To run the tests, check your test coverage, and generate an HTML coverage report:

  1. Run tests without test coverage analysis: uv run pytest
  • If the database schema has changed, use --create-db, as pytest will otherwise use the previous one (as it is much faster).
  • To see the slowest tests, use --durations=10 (to get the 10 slowest tests)
  1. Run test with test coverage analysis (and branch analysis) and create the html report: uv run coverage run --branch -m pytest && uv run coverage html
  2. You can find the report in htmlcov/index.html.

Continuous Integration (CI)

To help keeping a good style, GitLab is running the following pipeline after pushing to the repository:

  • pre-commit hook
  • pytest

Usage Guide

For Organizations

Registering an Organization

  1. Create a user account and verify your email
  2. Navigate to the Organizations section and click "Register New Organization"
  3. Fill in the required information about your organization
  4. Submit the form and wait for admin approval

Managing Resources

  1. Once your organization is approved, navigate to the Resources section
  2. Click "Add New Resource" to register a resource for sharing
  3. Fill in the resource details, including:
    • Name and description
    • Resource type
    • Availability schedule
    • Access information
    • Compensation requirements
    • Upload images of the resource
  4. Set any restrictions on who can book the resource and when
  5. Publish the resource to make it available for booking

Managing Bookings

  1. Navigate to the Bookings section to view all booking requests for your resources
  2. Approve or reject booking requests
  3. Communicate with users through the messaging system
  4. View your booking calendar to see all upcoming bookings

Configuring the free bookings allowance

Organizations can be limited to a number of free bookings per calendar year (see ADR 0023). Deploying the code changes nothing; the restriction starts with this configuration in the admin:

  1. Flag the free room compensation with Counts against free bookings. The flag is not allowed on compensations with a rate.
  2. On every organization group that should be limited, set Free bookings per year and Free bookings limit valid from (for example 2027-01-01). Both fields have to be set together. Leave member, self-help and rental groups empty: a group without a number grants unlimited free bookings, and the most generous group wins.
  3. Create paid hourly compensations for the rooms that should stay bookable once the free bookings are used. Rooms without one become unbookable for limited organizations for the rest of the year.
  4. Do this when the announcement goes out: bookings starting on or after the valid-from date are priced against the allowance from that moment, earlier bookings are not touched.

Changes to the number, the date or the flag only affect bookings priced afterwards. Booking series created before the configuration keep today's pricing in the nightly extension until the transition command marks them as quota-priced. When confirming new organizations, check that an organization is not being split only to multiply its allowance.

Transition of bookings created before the quota

After the announcement grace period, bring the remaining legacy bookings of limited organizations under the quota with one command:

  1. uv run python manage.py apply_free_bookings_quota --dry-run -v 2 prints, per organization, which future bookings keep the remaining free bookings of their year (earliest dates first), which are charged with the cheapest paid compensation of the room, which are removed because the room has no paid compensation, and which series get the fallback and the quota marker. Nothing is changed.
  2. Review the report and inform the affected organizations; the command sends no emails.
  3. uv run python manage.py apply_free_bookings_quota applies it. --organizations slug ... restricts a run to some organizations, so it can be done in batches.

Running the command again is safe: a completed organization reports "nothing to do". Past and invoiced bookings are never touched.

For Users

Finding Resources

  1. Browse the Resources section to see available resources
  2. Use filters to narrow down resources by type, location, or availability
  3. Click on a resource to view detailed information

Booking Resources

  1. Select the resource you want to book
  2. Choose the date and time for your booking
  3. For recurring bookings, set the frequency and end date
  4. Submit your booking request
  5. Wait for approval from the resource owner
  6. Once approved, you'll receive access information for the resource

Contribution Guidelines

We welcome contributions to the Re(source)-Sharing project! Here's how you can contribute:

Reporting Issues

  • Use the GitHub issue tracker to report bugs
  • Provide detailed steps to reproduce the issue
  • Include information about your environment

Contributing Code

  1. Fork the repository
  2. Create a new branch for your feature or bugfix
  3. Write tests for your changes
  4. Ensure all tests pass with uv run pytest
  5. Make sure your code follows our coding style (use uv run ruff format and uv run ruff check)
  6. Submit a pull request with a clear description of your changes

Documentation

  • Help improve the documentation by fixing typos or clarifying instructions
  • Add examples and use cases to make the documentation more helpful

Production

Deployment

For production deployment, follow these steps:

  1. Set up a production server with the required dependencies
  2. Configure environment variables for production settings
  3. Set up a PostgreSQL database
  4. Set up Redis for caching
  5. Configure a web server (e.g., Nginx) and WSGI server (e.g., Gunicorn)
  6. Set up SSL certificates for secure connections
  7. Deploy the application code
  8. Run migrations and collect static files
  9. Start the application

Scheduled commands for agreements

Run these once a day, for example from cron:

# Create fee collections within the lookahead and send pre-notifications
15 6 * * * python manage.py create_agreement_collections
# Mark debits collected after the return window, detect returns, sync paid return invoices
30 2 * * * python manage.py sync_collection_payments
# End agreements whose end date has passed
45 0 * * * python manage.py end_expired_agreements

Rolling out agreements

  1. Deploy, set the SEPA settings listed under Settings and add the three scheduled commands.
  2. Create the agreement kinds in the admin. Each kind lists its application fields (key, label, type, required, help text, choices, minimum, order); answers are stored under the key, which cannot be changed once created. Deactivate a field instead of deleting it once agreements have answered it.
    • Membership: yearly, the minimum amount, collection month 3 and the collection day, pre-notification "once with the approval", the member group, no accesses, no fields, applications open.
    • Coworking: monthly, deposit required, notice period, the coworking group, the accesses of its entrance code, fields desks and hours_per_week (whole numbers, minimum 1), applications open.
    • Office and cellar lease: monthly, fields room (text) and area_m2 (decimal, minimum 1), applications closed until their mandates exist.
    • Upload the contract as a fillable PDF under "Contract template". Its form fields are filled by name when the contract is downloaded from the agreement page; the kind's page lists which fields the template has and which are filled. Names: organization_name, organization_address, organization_phone, organization_email, organization_website, represented_by_person (checkbox), representative_name, representative_function, representative_email, amount, start_date, end_date, deposit_amount, kind_name, and detail_<key> for the kind's application fields. Other fields stay empty for the signer.
    • The SEPA mandate is generated with the creditor data from the settings, the mandate reference and the bank details; it needs no upload.
    • A kind's minimum amount binds applicants only; managers can enter lower amounts for existing agreements.
  3. Create and activate the email templates for the agreement emails (application received, manager notice, approved, rejected, ended, pre-notification, return invoice). The context offers organization, agreement, kind, agreement_url, mandate_reference, creditor_id, creditor_name, first_collection and, for collection emails, collection; bank details are never part of it.
  4. Enter existing members and coworkers as active agreements, each with its paper mandate reference, signed contract and signing date: managers use "New agreement" under Manage agreements (status "Active", which adds the kind's group if missing), staff can also use the admin (which changes no groups). Neither creates collections for periods due before the agreement was entered, entrance codes or emails.
  5. The first yearly member run follows in the next collection cycle, monthly runs from the following month. Check the first returned debit against the matching in the nightly command.
  6. Rollback: remove the scheduled commands. The tables stay; registration and bookings are unaffected.

Sentry

Sentry is an error logging aggregator service. You can sign up for a free account at https://sentry.io/ or download and host it yourself. The system is set up with reasonable defaults, including 404 logging and integration with the WSGI application.

You must set the DSN url in production.

Description taken from the repository README.

Ratings

–
0 ratings
5 0
4 0
3 0
2 0
1 0

Rate this app

Sign in to rate

Comments 0

Sign in to comment

No comments yet.

Related apps

#sharing · #booking · #social