Giter Club home page Giter Club logo

byro's Introduction

byro

GitHub release (with filter) PyPI - Version CI/CD Code coverage Code maintainability Documentation

byro is a membership administration tool for small and medium sized clubs/NGOs/associations of all kinds, with a focus on the DACH region. While it is still a work in progress, it is already usable and in active use.

https://raw.githubusercontent.com/byro/byro/main/docs/img/screenshots/office_dashboard.png

Development and Production Setup

Please refer to the development or the production documentation.

Features

Planned features

Official Plugins

byro provides a rich API for plugins. See our developer documentation if you want to write a plugin. If you want your plugin to be officially recognized or listed here, please open an issue or a pull request.

  • byro-mailman provides integration with the mailman mailing list tool, including automatic subscriptions, member lists, and removals.
  • byro-gemeinnuetzigkeit provides tools for German non-profits, most notably receipts for membership fees and donations.

Inofficial Plugins

Inofficial plugins are encouraged to add the byro-plugin tag if they are on GitHub. You can see all byro plugins on GitHub here.

  • byro-shackspace is an example for how a group can extend or modify byro to fit their purpose, e.g. add custom mechanisms and save additional data.

byro's People

Contributors

annikahannig avatar benediktg avatar cfstras avatar danimo avatar dependabot-preview[bot] avatar dependabot[bot] avatar dnet avatar fwolfst avatar goliathlabs avatar grosa1 avatar hdznrrd avatar henryk avatar herbetom avatar herr-dante avatar lemoer avatar luto avatar makefu avatar mfa avatar moritzfago avatar mraerino avatar oe1rfc avatar pc-coholic avatar rennerocha avatar rixx avatar schwindp avatar therojam avatar vollkorn1982 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

byro's Issues

install_local_plugins.sh fails when there are no local plugins

install_local_plugins.sh will return non-zero, if there are no plugins in the local-folder - as it is per default.

As far as I can tell, this is caused by for plugin in local/*; do returning local/*, if there is no subdirectory in local - which of course will then fail to cd into and install.

Fix is to set nullglob.

I'll provide a PR shortly.

Export member data

Provide an exporter that allows to choose member fields to export to csv.

Send a regular data report to each member

Data reports should contain all data we have on members. We should know when the last data report was sent out, and generate new mails once a year (configurable) has passed. Plugins need to be able to add their own data to this feature.

Send emails on membership termination

Email-wise, membership termination should work exactly as a member joining: Mails to the member, mails to the administration, plugin hooks to add additional information.

Needs to wait until we have a proper membership termintion action, though, otherwise it would get used on changed memberships aswell.

Add membership reporting (statistics)

Send a regular email to a set of addresses reporting on membership statistics for the past $interval.

Add options to configure the regularity and the email addresses per interval (e.g. monthly reports to the administration, yearly reports to the administration and membership mailing list).

Add plugin hooks to add information to these emails.

I tend to want this feature in byro-core, but we could put it in a plugin aswell, or a plugin that is shipped with byro-core. I'm open to suggestions as to the best direction in which to take this.

Terminate membership action

Memberships can currently be terminated by adding an end date to the last membership in the member data form, which is not good. We need a big button "terminate membership" that asks for a date, and then triggers all the appropriate actions (emails, checks, …).

Show statistics

  • Member statistics
    • must be provided via plugins
    • provide an example plugin for average age
    • Show number of new and terminated memberships per month
  • Transaction statistics
    • Missing payments (total and per month), overdue members
    • Received payments
  • Save statistics data separately

Trigger signal when membership data changes

Plugins may need to react to changing data, so a signal should be sent containing the old and the new data, after the member data has been saved.

Optionally(?) send emails on change.

Using Pipenv for dependencies

I was wondering if there were plans to switch from requirements.txt files to the new and much improved dependency handling principle with a Pipfile through Pipenv

Gains

  • Automatic virtualenv handling
    • pipenv install to create and install dependencies
    • pipenv shell to activate
    • pipenv run <cmd> to run something inside
  • Seperate Lockfile (Pipfile.lock)
  • Unified production and development dependencies

Use GPG

I'm not sure if GPG integration should be a plugin or a core feature – probably a vendored plugin would be best, that could be turned off or on, but will be shipped with byro automatically.

This issue includes key management for members, sending out emails to those members encrypted if they wish, and lots and lots of error handling.

Readme not very specific regarding first time startup

And another one ;-)

I guess, the following points are somewhere along the line of "Everyone knows that!" for seasoned Django-developers...

But in order to facilitate the initial setup for others that would like to get a feel for the project, I think the README should be extended a little bit.

  • In which directory has the local_settings.py to be dropped?
  • Which further steps are necessary in order to be able to use/log into the system
    • Running the migrations
    • Creating the superuser

Add user management

The board may change, so there should be a way to add new users and remove the old ones.

Membership management

Details

  • Create members
  • Update member data
  • Terminate membership (now or at $date)
  • Delete members by deleting all data, but keeping the objects themselves
    • Offer an option to defer data deletion due to outstanding fees etc
  • Mark data as outdated
  • (Pretty) print member data
  • Search and filter members

Add member interface

Members should be able to see their own data, maybe even change it. Authentication could be done via a secret link …

i18n all strings

There are quite some strings that need i18n atm:

  • Model field choices
  • (Missing) verbose_names on model fields
  • Template strings
  • Error messages

Emails when member data changes

The emails should work like the ones generated on new members: generate one mail for the member and one for the administration, and let plugins add their own data.

Settings

Provide settings via django-solo with sensible defaults. Provide a good plugin interface for plugin defined settings.

  • Data retention time after membership termination
  • Country
  • Currency
  • Language
  • Default membership fees
  • Name, templates, address, …

Members' meeting assistent

Introduce data model and assistent interface to initiate and work with Members' meetings:

  • Select whom to invite (by at least their balance)
  • Select whether to invite via mail or email
  • Send out invites
  • Export a list of invited members (including a signature fields to sign in maybe?)

Member communication: emails

Details

  • Send and edit emails both via templates and without.
  • Send automated emails
    • When member data is updated
    • When member fees are overdue
    • Welcome mail
    • Confirm membership termination
    • Yearly information on member data
  • Send signed/encrypted emails
  • Queue (editable) emails before sending
  • Derive ordinary mail from e-mail

error on first time use

As a first-time user I followed the README instructions.

I execute the commands from within byro/src/

  • add local_settings.py in the src/byro/ folder with the provided contents
  • create the database using docker-compose run --rm web reset_db which eventually says
    • psycopg2.ProgrammingError: database "byro" does not exist
    • Reset successful.
  • start the byro service docker-compose up -d

The error I get is the following (in the browser):

  • http://localhost:8020/ redirects to http://localhost:8020/login/?next=/
ProgrammingError at /login/

relation "common_configuration" does not exist
LINE 1: ...on_form", "common_configuration"."mail_from" FROM "common_co...


Request Method: GET
Request URL: http://localhost:8020/login/?next=/
Django Version: 1.11.10
Exception Type: ProgrammingError
Exception Value: relation "common_configuration" does not exist LINE 1: ...on_form", "common_configuration"."mail_from" FROM "common_co...                                                              ^
Exception Location: /usr/local/lib/python3.6/site-packages/django/db/backends/utils.py in execute, line 64
Python Executable: /usr/local/bin/python
Python Version: 3.6.4
Python Path: ['/opt/code',  '/usr/local/lib/python36.zip',  '/usr/local/lib/python3.6',  '/usr/local/lib/python3.6/lib-dynload',  '/usr/local/lib/python3.6/site-packages',  '/opt/code']
Server time: Fri, 2 Feb 2018 11:06:50 +0000

and

Environment:


Request Method: GET
Request URL: http://localhost:8020/login/?next=/

Django Version: 1.11.10
Python Version: 3.6.4
Installed Applications:
['django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'compressor',
 'bootstrap4',
 'djangoformsetjs',
 'solo.apps.SoloAppConfig',
 'byro.common.apps.CommonConfig',
 'byro.bookkeeping.apps.BookkeepingConfig',
 'byro.documents.apps.DocumentsConfig',
 'byro.mails.apps.MailsConfig',
 'byro.members.apps.MemberConfig',
 'byro.office.apps.OfficeConfig',
 'byro.plugins.profile.ProfilePluginConfig',
 'byro.plugins.sepa.SepaPluginConfig',
 'annoying',
 'django_extensions']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'byro.common.middleware.PermissionMiddleware']



Traceback:

File "/usr/local/lib/python3.6/site-packages/django/db/backends/utils.py" in execute
  64.                 return self.cursor.execute(sql, params)

The above exception (relation "common_configuration" does not exist
LINE 1: ...on_form", "common_configuration"."mail_from" FROM "common_co...
                                                             ^
) was the direct cause of the following exception:

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
  41.             response = get_response(request)

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  217.                 response = self.process_exception_by_middleware(e, request)

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  215.                 response = response.render()

File "/usr/local/lib/python3.6/site-packages/django/template/response.py" in render
  107.             self.content = self.rendered_content

File "/usr/local/lib/python3.6/site-packages/django/template/response.py" in rendered_content
  84.         content = template.render(context, self._request)

File "/usr/local/lib/python3.6/site-packages/django/template/backends/django.py" in render
  66.             return self.template.render(context)

File "/usr/local/lib/python3.6/site-packages/django/template/base.py" in render
  205.                 with context.bind_template(self):

File "/usr/local/lib/python3.6/contextlib.py" in __enter__
  81.             return next(self.gen)

File "/usr/local/lib/python3.6/site-packages/django/template/context.py" in bind_template
  263.             updates.update(processor(self.request))

File "/opt/code/byro/common/context_processors.py" in byro_information
  11.     ctx = {'config': Configuration.get_solo()}

File "/usr/local/lib/python3.6/site-packages/solo/models.py" in get_solo
  54.             obj, created = cls.objects.get_or_create(pk=cls.singleton_instance_id)

File "/usr/local/lib/python3.6/site-packages/django/db/models/manager.py" in manager_method
  85.                 return getattr(self.get_queryset(), name)(*args, **kwargs)

File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py" in get_or_create
  464.             return self.get(**lookup), False

File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py" in get
  374.         num = len(clone)

File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py" in __len__
  232.         self._fetch_all()

File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py" in _fetch_all
  1118.             self._result_cache = list(self._iterable_class(self))

File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py" in __iter__
  53.         results = compiler.execute_sql(chunked_fetch=self.chunked_fetch)

File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/compiler.py" in execute_sql
  899.             raise original_exception

File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/compiler.py" in execute_sql
  889.             cursor.execute(sql, params)

File "/usr/local/lib/python3.6/site-packages/django/db/backends/utils.py" in execute
  79.             return super(CursorDebugWrapper, self).execute(sql, params)

File "/usr/local/lib/python3.6/site-packages/django/db/backends/utils.py" in execute
  64.                 return self.cursor.execute(sql, params)

File "/usr/local/lib/python3.6/site-packages/django/db/utils.py" in __exit__
  94.                 six.reraise(dj_exc_type, dj_exc_value, traceback)

File "/usr/local/lib/python3.6/site-packages/django/utils/six.py" in reraise
  685.             raise value.with_traceback(tb)

File "/usr/local/lib/python3.6/site-packages/django/db/backends/utils.py" in execute
  64.                 return self.cursor.execute(sql, params)

Exception Type: ProgrammingError at /login/
Exception Value: relation "common_configuration" does not exist
LINE 1: ...on_form", "common_configuration"."mail_from" FROM "common_co...
                                                             ^

Add default importer

We should define our own JSON format and write an importer for that, so that others don't have to.

We should also consider adding a CSV importer for member data only. If we want to import everything, we need JSON (or multiple CSVs to be imported in the correct order, which seems very unwieldy and wrong), but for membership data only, we could offer this, and all people coming from "oh, I have my members in an excel file" could just use it.

Naturally, plugins should be offered a hook to declare their own importers so they don't have to do all the legwork themselves.

Write transaction tests

- Mitglied schuldet über Jahresgrenzen Mitgliederbeiträge
- Mitglied stirbt und hat ein nichttriviales (= nicht ausgeglichenes) Konto
- Mitglied verliert Geschäftsfähigkeit
- Mehr als ein Beitrag für Fremdperson
  (eine Person überweist für sich selbst und jemand anderen)
- Mehr als ein Beitrag für sich selbst
  (mehr Beitrag für Rechnungsperiode)
- Teilbeitrag
- Beitrag + Spende
- Rückzahlung wegen Beitrag + Überzahlung 
    - Rückzahlung auf ein anderes Konto
- Lastschrift wird rückgebucht
- Gebühren / Mehraufwandsgebühren <- auf eigenes Konto
- Mitgliedsbeitrag verrechnet mit Auszahlung/anderweitigen Guthaben
- Beitrag für zwei oder mehr Leute, wobei die Zahlung für keinen eigenen reicht
    - dem für den mitgezahlt wurde, wird alles gutgeschrieben
- Beitrag für mehr als zwei Leute, wobei die Zahlung nicht für die anderen reicht.
    - unklar was mit dem Betrag geschehen soll
- oder (zwei letzte): allen Mitgezahlten wird alles gut geschrieben, dem Zahlenden die Differenz in soll gestellt.
- Beiträge (Standardbeitrag soll geprüft werden)
- Beträge, die im Nachhinein (nach abgeschlossener Rechnungsperiode z.B. 2017 für 2015)
- Rückbuchungsarten von Lastschriften (sort of informativ) (für Buchhaltungszukunft?)
  - Konto nicht gedeckt / unbekannter / sonstiger Grund
  - Lastschrift rejected
  - Konto existiert nicht
  -> weitere Lastschriften stoppen

Allow to create members with no e-mail address

Current logic in https://github.com/byro/byro/blob/master/src/byro/office/views/members.py#L94 hardcodes an attempt to send an e-mail to the address in the email field in the new member form.
If that field is empty or non-present, an IntegrityError is raised, because an attempt is made to create an "EMail" model with NULL to address.

Should we either:

  • Not try to send the member welcome mail if no email address is entered?
  • Or: Put it into outbox, with some marking and default to address (vorstand?) so that it can be manually re-adressed or deleted as appropriate?

Import member data

Provide an import plugin for member imports. Test with generated data.

Emails on overdue fees

Add an action to send emails to members with overdue fees.

Add an option to send (as in: queue) these emails automatically.

Add a plugin hook so that plugins can provide additional text to those emails.

Allow to mark member data as outdated

Member data may be outdated, but we will still retain it until we have new information. So we should be able to mark a member as "has outdated data" and provide a list of outdated fields.

JVerein-Importer

I have the feeling that a JVerein importer would be well-received.

Somebody with useful JVerein data could anonymise the data, and provide it for testing purposes.

Add member documents

Members do have documents. Documents may have types, names, descriptions, etc

Spell-check documentation

Also, can we spell-check translation files? They're already marked with their locale, so this should be a solved problem.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.