Giter Site home page Giter Site logo

conoscerelinux / asso-django Goto Github PK

View Code? Open in Web Editor NEW
0.0 0.0 3.0 449 KB

An open source Django Framework to manage Events, Member and basic Accounting for an Italian Association

License: GNU General Public License v3.0

Python 82.18% Makefile 1.57% HTML 5.61% CSS 10.26% JavaScript 0.37%

asso-django's People

Contributors

giobber avatar zompasenior avatar

Watchers

 avatar  avatar

asso-django's Issues

MemberRegister and RegisterEntry

They are related to transaction and the process of Member registration. They should manage a Member who is registered and calling for Membership creation or renovation.
More clarification and documentation is needed on how they should work

  • What's the scope of MembershipRegister? It's really needed?
  • How RegisterEntry is supposed to work?
  • How they should connect to transaction model?

Remove division between production and development requirements.txt

production and development requirements are at the moment separate files.
This was made to accomplish a common pattern in my personal projects which became obsolete after introducing pyproject.toml as python project management file.

  • Remove requirements.dev.txt and reference of it in makefile
  • Change commands in makefile to send development enviroment in requirements.txt
  • Use pip install . to install production dependencies

Create a unique script to handle importation of data

Data should be loaded with a single script load_data.py which load a sample site and sample data

  • Two separate script to handle theme and data separatly could be a good idea
  • Data loading should be managed inside Django Manager class not inside scripts
  • scripts should only handle reading from json file, prepare dictionaries and send to Managers

Make requirements.txt more available

Conda support

A possible solution is to create a requirements.conda.txt or simply test our requirements in a conda environment (exploiting conda support to multiple python versions)

Better defaults

  • Set python to 3.10

A proposal for a multi mail User/Member

  • User onetoone Member
  • User.username is keep, User.mail is keep
  • new model MemberMail with a fields:
    • mail = EmailField(unique=True, null=False, blank=False)
    • member o user via ForeignKey
  • in member views, a field with "administrative mail" is view and modified separately and link to User.mail. On change, a check against UserMail.mail is made to ensure a mail is not inserted twice
  • in member views, additional mail table point to MemberMail mails and check on insertion if mail is present as User.mail or a UserMails.mail before accepting changes
  • in login via admin page nothing change, only username works
  • in login for members (view), POST request pass (username, password):
    • if username is a valid User.username => login(username, password)
    • if username is a valid User.mail => login(user.username, password)
    • if username is a valid UserMail.mail => login(umail.user.username, password)

NOTE: in the unfortunate event that a UserMail.mail coincide with a User.mail (maybe for some strage internal error or an admin oversight), User.mail will have always precedence over UserMail.mail with this setup

Some correction in makefile

  • Add -f in bootstrap-django command (rm-f db.sqlite3)
  • Remove division between dev and prod (see #15 for more info)
  • Add comments to explain what various command do
  • rename freeze in requirements

Core | Separate models in models/common and models/user

For reference see documentation

  • convert models in a module: from core/models.py to core/models/__init__.py
  • separate user related models in a separate sub-module (core/models/user.py)
  • move common abstract classes in a sub-module called core/models/common.py
  • (optional) import all models inside __init__ for backward compatibility

Models | Complete Member fields

Generic and contact info

  • user
  • first name
  • last name
  • phone
  • Note (no migration from old data)

Personal Data

  • cf (with basic validator)
  • sex/gender
  • birth_date
  • birth_place (city/province)

Address

  • description
  • number
  • city
  • postal code (CAP)
  • province code (XX)

Document

  • type (carta-identità, patente, passaporto)
  • grant_from
  • code
  • Expiration date

Marketing

  • professione_member
  • titolo_studio_member (None, master-universitario, licenza-media, laurea-triennale, laurea-magistrale, laurea, elementari,dottorato-ricerca, diploma-superiore, diploma-professionale, diploma-maturità, diploma-ragioneria)
  • conosciuto_member (amici, compagni-colleghi, eventi, fiere, internet, lavoro, motori-ricerca, passaparola, pubblicità, volantino)
  • interessi_member

Privacy

  • associazione
  • corsi
  • newsletter

Codice Fiscale should be validated and check if unique

Description

"Codice Fiscale" field should be unique as it represent the unique ID of a person in Italy
There are two main problems:

  • CF are not always unique, this was solved by using omocodes but is common online for users to avoid using his personal omocode and instead using the not omocode CF to avoid problem with too much simpler validation
  • A lot of people insert wrong CF because of typos, memory, laziness (see #50 for possible solutions)
  • For foreign person (mainly immigrants) is common to use not so clean data when registering in Italy...so a lot of omocodes and strange CF
  • No good database of province is available, python-codicefiscale has a good solution but in general is a best effort

Solution

  • Set Member.cf as unique=False (to permit foreign and strange CF to pass)
  • Add field `Member.skip_cf_valid = models.BooleanField(default=False)
  • Add validator in Member to check if Member.cf is valid (see #50 )
  • Add validator in Member to check if Member.cf is unique unless Member.skip_cf_valid=True

Django project structure

Actually project has this structure (as presented in Django tutorial)

asso-django/
  admin/
  academy/
  common/
  ...
  website/
  manage.py

Django REST Framework propose another way

asso-django/
  admin/
    academy/
    common/
    ...
    website/
  manage.py

This way all apps are contained inside admin package (which could be called asso)

Also this structure permits to convert common app (which is never used as app) in a normal python module

Membership | How TimePeriod work

TimePeriod describe a formal timeframe of membership validation
For example a membership record on 10th of February 2023 should be valid throught 1st of January 2023 to 31th of December 2023 if the formal timeframe chosen by association is the solar year for members registered in 2023

@ZompaSenior has proposed to implement it with a start and a duration (using RelativeDeltaField field)

Implementation

class TimePeriod:
    start = models.DateField(...)
    duration = models.DateField(...) 
    price = models.MoneyField(...)

Question: using end_date instead of duration

An additional end=models.DateField(...) field could be added with a validation which impose that one and only one between duration or end field should be set. Or substituting duration with end. This should permit more fine selection of date interval, but make more complex to set regular interval (yearly, bimonthly, etc, etc)...I think response is obvious

Some notes

  • TimePeriod.duration == None could be used to intend a membership which doesn't end
  • TimePeriod.start == None could be used to intend a membership which is retroactively always valid
  • is not completely clear what field price is referring to, as is I think is the default price to create a membership for that period. In fact discounted or free memberships should be permits. I think this last observation is linked to logic inside Transaction connected to membership model

What to do

  • Convert default in duration from formal string to a relativedelta from a function
  • Specify price help text
  • (optional) Add some method to create common relativedelta timeframe)

Installation instructions

@giobber it could be great if you can provide some instructions on how to use your installation system, if you think it could be the main way to perform.
Otherwise we can collect together some instructions for a more general way.

Event Sessions

In my opinion, it is possible to avoid inserting the field relating to the date and times of an Event in the model of the Event itself, as this information can be indicated in its first Session.

In fact, barring logical wreckage, in the case of multiple Sessions of an Event, it would still be necessary to indicate the information for each Session, including the first, so in my opinion you could simply make sure that you always have a first Session automatically generated with information relating to the date and times, and then be able to add more if necessary.

In this mode, the sorting of Events on the site could be based directly on the dates of the Sessions, and also allow logics in which Events can remain visible, if Sessions are yet to take place (perhaps with an option that allows you to avoid it when no appropriate).

Membership Model

This issues contains all the info to complete Membership model

MembershipPeriod

  • Remove help_text in MembershipPeriod fields
  • Improve __str__ by making it fallback to f"{start}-{end}"

MemberRegister and RegisterEntry

Moved to issue #69

Membership

  • Add a __str__ (for example f"{str(self.period)}/{self.card_number}"
  • Improve and translate docstrings, help_text and verbose names if and where needed

Member model improvements

  • Add third option to gender option (Male|Female|Other)
  • re-add name, surname here (does not depend on user, teacher will have a display_name, display_surname)
  • Codice Fiscale / Social ID
    • set max_length of CF to 20/24 (validity will be check in form)
    • Add method to check social_id formal validity and against other personal data (see #81)
    • Add social_id validator (see #64)
    • Move CF check in MemberForm
  • Move phone check in MemberForm
  • Add a model to handle DocumentType
  • Remove document_expires default (imported data will use a default)

Remove ipython from dev dependencies

  • Remove ipython from dev dependencies
  • Add reference in README to install it if you want ipython support through django shell_plus
  • add command in makefile (make shell)

Member | Convert Member to a subclass of User

One of the ways to extend a model in django is via inheritance, essentially when i subclass a model in django it create a hidden OneToOneField relation (unique=True, primary=True, null=False) by using Base class index as index for children.

For more info see Django Documentation

Pro

  • Member is always connected to a single User
  • Teacher and Member now could be coexists without problem
  • I could still create a User without Member or Teacher
  • first_name, last_name and email now are set and accessed between User, Member and Teacher without useless complications

Contro

  • I cannot create Member without User (but we already decided it complicates relations)
  • I cannot delete user without deleting associated Members/Teachers (see above)
  • At the moment is required to extend User model by calling it directly which is not best practice

Sample code

from ..core.models import User

class Member(User):
  ...

Member | Check personal data against codicefiscale

python-codicefiscale permit to check if Codice Fiscale is compatible with personal data

This can be done inside the view or as a Member validator. The first one IMHO is the more feasible way to use it.
Implementation could be done as a class method check_cf_data

NOTE: Only problem with this is that python-codicefiscale require birth city written in a very specific way, but admits variations. So we can check if data inserted by user is compatible with a variation and substitute it with the library's chosen one.

Proposal for User/Member structure

Objective

Make login available with multiple user emails and username

Structure

class User(AbstractBaseUser):
    username = models.CharField(max_length=40, unique=True)
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)
    password = ...

    USERNAME_FIELD = "username"

    objects = UserManager()
    @property
    def email(self):
         return self.emails.filter(primary=True).first()

class UserEmail(Model):
    email = EmailField(unique=True)
    user = ForeignKey(User)
    primary = BoolUniqueForUser()  # Mail used for communications
# Inside membership module
from django.conf import settings
from django.contrib.auth import get_user_model

class Member:
    ...
    user = OneToOneField(settings.AUTH_USER_MODEL)
    ...

Reference

  • Useful article: link
  • documentation: link

What to do to avoid CircularDependencyError error on migrations

link to documentation

  • Create new auth app inside admin (require models.py, admin.py, 'migrationsandapps.py`
  • Create custom user, without any difference with default user
  • link that user to auth_user table
  • Connect new app in settings by:
    • adding App class in apps.py with name admin.auth
    • adding admin.auth.apps.AuthApp to settings.INSTALLED_APPS
  • migrate
  • make required changes to User class and migrate it

If this not work (and probably will) take a breath, remove all migrations for user and memberships and start anew (fortunately we are still in alpha), the other models migrations will live fine

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.