1
0
mirror of https://gitlab.crans.org/bde/nk20 synced 2024-11-26 18:37:12 +00:00

Merge branch 'docs' into 'beta'

Docs

See merge request bde/nk20!145
This commit is contained in:
ynerant 2021-01-19 12:01:45 +01:00
commit 8d71783c42
39 changed files with 6705 additions and 2 deletions

View File

@ -1,6 +1,7 @@
stages:
- test
- quality-assurance
- docs
# Also fetch submodules
variables:
@ -62,3 +63,17 @@ linters:
# Be nice to new contributors, but please use `tox`
allow_failure: true
# Compile documentation
documentation:
stage: docs
image: sphinxdoc/sphinx
before_script:
- pip install sphinx-rtd-theme
- cd docs
script:
- make dirhtml
artifacts:
paths:
- docs/_build
expire_in: 1 day

View File

@ -16,3 +16,4 @@
- 5-nginx
- 6-psql
- 7-postinstall
- 8-docs

View File

@ -50,6 +50,10 @@ server {
alias /var/www/note_kfet/static; # your Django project's static files - amend as required
}
location /doc {
alias /var/www/documentation; # The documentation of the project
}
# Finally, send all non-media requests to the Django server.
location / {
uwsgi_pass note;

View File

@ -0,0 +1,20 @@
---
- name: Install Sphinx and RTD theme
pip:
requirements: /var/www/note_kfet/docs/requirements.txt
virtualenv: /var/www/note_kfet/env
virtualenv_command: /usr/bin/python3 -m venv
virtualenv_site_packages: true
become_user: www-data
- name: Create documentation directory with good permissions
file:
path: /var/www/documentation
state: directory
owner: www-data
group: www-data
mode: u=rwx,g=rwxs,o=rx
- name: Build HTML documentation
command: /var/www/note_kfet/env/bin/sphinx-build -b dirhtml /var/www/note_kfet/docs/ /var/www/documentation/
become_user: www-data

View File

@ -32,4 +32,4 @@ class RoleViewSet(ReadOnlyProtectedModelViewSet):
serializer_class = RoleSerializer
filter_backends = [DjangoFilterBackend, SearchFilter]
filterset_fields = ['name', 'permissions', 'for_club', 'memberships__user', ]
SearchFilter = ['$name', '$for_club__name', ]
search_fields = ['$name', '$for_club__name', ]

20
docs/Makefile Normal file
View File

@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

344
docs/_static/img/graphs/activity.svg vendored Normal file
View File

@ -0,0 +1,344 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.44.1 (0)
-->
<!-- Title: model_graph Pages: 1 -->
<svg width="578pt" height="729pt"
viewBox="0.00 0.00 578.00 729.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 725)">
<title>model_graph</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-725 574,-725 574,4 -4,4"/>
<!-- activity_models_ActivityType -->
<g id="node1" class="node">
<title>activity_models_ActivityType</title>
<polygon fill="white" stroke="transparent" points="8,-4 8,-92 186,-92 186,-4 8,-4"/>
<polygon fill="#1b563f" stroke="transparent" points="9,-70 9,-91 185,-91 185,-70 9,-70"/>
<text text-anchor="start" x="51" y="-79" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="61" y="-79" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;ActivityType &#160;&#160;&#160;</text>
<text text-anchor="start" x="11" y="-62.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21" y="-62.6" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="29" y="-62.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="93" y="-62.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="103" y="-62.6" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="141" y="-62.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11" y="-49.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21" y="-49.6" font-family="Roboto" font-size="8.00">can_invite</text>
<text text-anchor="start" x="57" y="-49.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="93" y="-49.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="103" y="-49.6" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="149" y="-49.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11" y="-36.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21" y="-36.6" font-family="Roboto" font-size="8.00">guest_entry_fee</text>
<text text-anchor="start" x="79" y="-36.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="93" y="-36.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="103" y="-36.6" font-family="Roboto" font-size="8.00">PositiveIntegerField</text>
<text text-anchor="start" x="173" y="-36.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11" y="-23.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21" y="-23.6" font-family="Roboto" font-size="8.00">manage_entries</text>
<text text-anchor="start" x="79" y="-23.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="93" y="-23.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="103" y="-23.6" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="149" y="-23.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11" y="-10.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21" y="-10.6" font-family="Roboto" font-size="8.00">name</text>
<text text-anchor="start" x="42" y="-10.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="93" y="-10.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="103" y="-10.6" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="138" y="-10.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="8,-4 8,-92 186,-92 186,-4 8,-4"/>
</g>
<!-- activity_models_Activity -->
<g id="node2" class="node">
<title>activity_models_Activity</title>
<polygon fill="white" stroke="transparent" points="197,-145 197,-324 369,-324 369,-145 197,-145"/>
<polygon fill="#1b563f" stroke="transparent" points="198,-301.5 198,-322.5 368,-322.5 368,-301.5 198,-301.5"/>
<text text-anchor="start" x="248" y="-310.5" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="258" y="-310.5" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;Activity &#160;&#160;&#160;</text>
<text text-anchor="start" x="200" y="-294.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="210" y="-294.1" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="218" y="-294.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="285" y="-294.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="295" y="-294.1" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="333" y="-294.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="200" y="-281.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="210" y="-281.1" font-family="Roboto" font-weight="bold" font-size="8.00">activity_type</text>
<text text-anchor="start" x="261" y="-281.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="285" y="-281.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="295" y="-281.1" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="356" y="-281.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="200" y="-268.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="210" y="-268.1" font-family="Roboto" font-weight="bold" font-size="8.00">attendees_club</text>
<text text-anchor="start" x="271" y="-268.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="285" y="-268.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="295" y="-268.1" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="356" y="-268.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="200" y="-255.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="210" y="-255.1" font-family="Roboto" font-weight="bold" font-size="8.00">creater</text>
<text text-anchor="start" x="238" y="-255.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="285" y="-255.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="295" y="-255.1" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="356" y="-255.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="200" y="-242.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="210" y="-242.1" font-family="Roboto" font-weight="bold" font-size="8.00">organizer</text>
<text text-anchor="start" x="247" y="-242.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="285" y="-242.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="295" y="-242.1" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="356" y="-242.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="200" y="-229.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="210" y="-229.1" font-family="Roboto" font-size="8.00">date_end</text>
<text text-anchor="start" x="244" y="-229.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="285" y="-229.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="295" y="-229.1" font-family="Roboto" font-size="8.00">DateTimeField</text>
<text text-anchor="start" x="347" y="-229.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="200" y="-216.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="210" y="-216.1" font-family="Roboto" font-size="8.00">date_start</text>
<text text-anchor="start" x="247" y="-216.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="285" y="-216.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="295" y="-216.1" font-family="Roboto" font-size="8.00">DateTimeField</text>
<text text-anchor="start" x="347" y="-216.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="200" y="-203.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="210" y="-203.1" font-family="Roboto" font-size="8.00">description</text>
<text text-anchor="start" x="249" y="-203.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="285" y="-203.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="295" y="-203.1" font-family="Roboto" font-size="8.00">TextField</text>
<text text-anchor="start" x="327" y="-203.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="200" y="-190.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="210" y="-190.1" font-family="Roboto" font-size="8.00" fill="#7b7b7b">location</text>
<text text-anchor="start" x="238" y="-190.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="285" y="-190.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="295" y="-190.1" font-family="Roboto" font-size="8.00" fill="#7b7b7b">CharField</text>
<text text-anchor="start" x="330" y="-190.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="200" y="-177.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="210" y="-177.1" font-family="Roboto" font-size="8.00">name</text>
<text text-anchor="start" x="231" y="-177.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="285" y="-177.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="295" y="-177.1" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="330" y="-177.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="200" y="-164.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="210" y="-164.1" font-family="Roboto" font-size="8.00">open</text>
<text text-anchor="start" x="229" y="-164.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="285" y="-164.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="295" y="-164.1" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="341" y="-164.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="200" y="-151.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="210" y="-151.1" font-family="Roboto" font-size="8.00">valid</text>
<text text-anchor="start" x="226" y="-151.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="285" y="-151.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="295" y="-151.1" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="341" y="-151.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="197,-145 197,-324 369,-324 369,-145 197,-145"/>
</g>
<!-- activity_models_Activity&#45;&gt;activity_models_ActivityType -->
<g id="edge1" class="edge">
<title>activity_models_Activity&#45;&gt;activity_models_ActivityType</title>
<path fill="none" stroke="black" d="M183.88,-135.18C170.27,-121.68 156.83,-108.35 144.74,-96.35"/>
<ellipse fill="black" stroke="black" cx="186.89" cy="-138.16" rx="4" ry="4"/>
<text text-anchor="middle" x="197" y="-116.6" font-family="Roboto" font-size="8.00"> activity_type (+)</text>
</g>
<!-- django_contrib_auth_models_User -->
<g id="node6" class="node">
<title>django_contrib_auth_models_User</title>
<polygon fill="white" stroke="transparent" points="220,-37.5 220,-58.5 264,-58.5 264,-37.5 220,-37.5"/>
<polygon fill="#1b563f" stroke="transparent" points="220,-37 220,-58 264,-58 264,-37 220,-37"/>
<text text-anchor="start" x="224" y="-45.4" font-family="Roboto" font-size="8.00"> &#160;</text>
<text text-anchor="start" x="229" y="-45.4" font-family="Roboto" font-size="12.00" fill="white">User</text>
<text text-anchor="start" x="255" y="-45.4" font-family="Roboto" font-size="8.00"> &#160;</text>
</g>
<!-- activity_models_Activity&#45;&gt;django_contrib_auth_models_User -->
<g id="edge2" class="edge">
<title>activity_models_Activity&#45;&gt;django_contrib_auth_models_User</title>
<path fill="none" stroke="black" d="M245.08,-133.07C244.3,-129.69 243.61,-126.33 243,-123 239.5,-103.79 239.8,-81.3 240.63,-66.2"/>
<ellipse fill="black" stroke="black" cx="246.06" cy="-137.08" rx="4" ry="4"/>
<text text-anchor="middle" x="272.5" y="-116.6" font-family="Roboto" font-size="8.00"> creater (activity)</text>
</g>
<!-- member_models_Club -->
<g id="node7" class="node">
<title>member_models_Club</title>
<polygon fill="white" stroke="transparent" points="338,-37.5 338,-58.5 382,-58.5 382,-37.5 338,-37.5"/>
<polygon fill="#1b563f" stroke="transparent" points="338,-37 338,-58 382,-58 382,-37 338,-37"/>
<text text-anchor="start" x="342" y="-45.4" font-family="Roboto" font-size="8.00"> &#160;</text>
<text text-anchor="start" x="347" y="-45.4" font-family="Roboto" font-size="12.00" fill="white">Club</text>
<text text-anchor="start" x="373" y="-45.4" font-family="Roboto" font-size="8.00"> &#160;</text>
</g>
<!-- activity_models_Activity&#45;&gt;member_models_Club -->
<g id="edge3" class="edge">
<title>activity_models_Activity&#45;&gt;member_models_Club</title>
<path fill="none" stroke="black" d="M316.94,-133.22C319.56,-126.67 322.25,-120.22 325,-114 332.41,-97.23 342.46,-78.92 349.89,-66.01"/>
<ellipse fill="black" stroke="black" cx="315.37" cy="-137.22" rx="4" ry="4"/>
<text text-anchor="middle" x="349.5" y="-116.6" font-family="Roboto" font-size="8.00"> organizer (+)</text>
</g>
<!-- activity_models_Activity&#45;&gt;member_models_Club -->
<g id="edge4" class="edge">
<title>activity_models_Activity&#45;&gt;member_models_Club</title>
<path fill="none" stroke="black" d="M369.62,-133.72C371.23,-130.19 372.7,-126.61 374,-123 380.76,-104.17 374.44,-81.42 368.26,-66.15"/>
<ellipse fill="black" stroke="black" cx="367.85" cy="-137.32" rx="4" ry="4"/>
<text text-anchor="middle" x="412" y="-116.6" font-family="Roboto" font-size="8.00"> attendees_club (+)</text>
</g>
<!-- activity_models_Entry -->
<g id="node3" class="node">
<title>activity_models_Entry</title>
<polygon fill="white" stroke="transparent" points="284,-518 284,-606 448,-606 448,-518 284,-518"/>
<polygon fill="#1b563f" stroke="transparent" points="285,-584 285,-605 447,-605 447,-584 285,-584"/>
<text text-anchor="start" x="336.5" y="-593" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="346.5" y="-593" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;Entry &#160;&#160;&#160;</text>
<text text-anchor="start" x="287" y="-576.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="297" y="-576.6" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="305" y="-576.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="340" y="-576.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="350" y="-576.6" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="388" y="-576.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="287" y="-563.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="297" y="-563.6" font-family="Roboto" font-weight="bold" font-size="8.00">activity</text>
<text text-anchor="start" x="326" y="-563.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="340" y="-563.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="350" y="-563.6" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="411" y="-563.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="287" y="-550.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="297" y="-550.6" font-family="Roboto" font-weight="bold" font-size="8.00">guest</text>
<text text-anchor="start" x="320" y="-550.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="340" y="-550.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="350" y="-550.6" font-family="Roboto" font-weight="bold" font-size="8.00">OneToOneField (id)</text>
<text text-anchor="start" x="426" y="-550.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="287" y="-537.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="297" y="-537.6" font-family="Roboto" font-weight="bold" font-size="8.00">note</text>
<text text-anchor="start" x="315" y="-537.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="340" y="-537.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="350" y="-537.6" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (note_ptr)</text>
<text text-anchor="start" x="435" y="-537.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="287" y="-524.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="297" y="-524.6" font-family="Roboto" font-size="8.00">time</text>
<text text-anchor="start" x="313" y="-524.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="340" y="-524.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="350" y="-524.6" font-family="Roboto" font-size="8.00">DateTimeField</text>
<text text-anchor="start" x="402" y="-524.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="284,-518 284,-606 448,-606 448,-518 284,-518"/>
</g>
<!-- activity_models_Entry&#45;&gt;activity_models_Activity -->
<g id="edge5" class="edge">
<title>activity_models_Entry&#45;&gt;activity_models_Activity</title>
<path fill="none" stroke="black" d="M268.49,-526.87C243.03,-513.01 218.65,-494.17 204,-469 178.65,-425.45 193.33,-372.56 216.59,-328.14"/>
<ellipse fill="black" stroke="black" cx="272.15" cy="-528.79" rx="4" ry="4"/>
<text text-anchor="middle" x="233" y="-419.1" font-family="Roboto" font-size="8.00"> activity (entries)</text>
</g>
<!-- activity_models_Guest -->
<g id="node4" class="node">
<title>activity_models_Guest</title>
<polygon fill="white" stroke="transparent" points="279.5,-377 279.5,-465 452.5,-465 452.5,-377 279.5,-377"/>
<polygon fill="#1b563f" stroke="transparent" points="281,-443 281,-464 452,-464 452,-443 281,-443"/>
<text text-anchor="start" x="335.5" y="-452" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="345.5" y="-452" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;Guest &#160;&#160;&#160;</text>
<text text-anchor="start" x="283" y="-435.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="293" y="-435.6" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="301" y="-435.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="345" y="-435.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="355" y="-435.6" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="393" y="-435.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="283" y="-422.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="293" y="-422.6" font-family="Roboto" font-weight="bold" font-size="8.00">activity</text>
<text text-anchor="start" x="322" y="-422.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="345" y="-422.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="355" y="-422.6" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="416" y="-422.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="283" y="-409.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="293" y="-409.6" font-family="Roboto" font-weight="bold" font-size="8.00">inviter</text>
<text text-anchor="start" x="318" y="-409.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="345" y="-409.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="355" y="-409.6" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (note_ptr)</text>
<text text-anchor="start" x="440" y="-409.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="283" y="-396.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="293" y="-396.6" font-family="Roboto" font-size="8.00">first_name</text>
<text text-anchor="start" x="331" y="-396.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="345" y="-396.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="355" y="-396.6" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="390" y="-396.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="283" y="-383.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="293" y="-383.6" font-family="Roboto" font-size="8.00">last_name</text>
<text text-anchor="start" x="330" y="-383.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="345" y="-383.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="355" y="-383.6" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="390" y="-383.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="279.5,-377 279.5,-465 452.5,-465 452.5,-377 279.5,-377"/>
</g>
<!-- activity_models_Entry&#45;&gt;activity_models_Guest -->
<g id="edge7" class="edge">
<title>activity_models_Entry&#45;&gt;activity_models_Guest</title>
<path fill="none" stroke="black" d="M366,-513.94C366,-499.45 366,-483.5 366,-469.01"/>
<text text-anchor="middle" x="390.5" y="-489.6" font-family="Roboto" font-size="8.00"> guest (entry)</text>
</g>
<!-- note_models_notes_NoteUser -->
<g id="node8" class="node">
<title>note_models_notes_NoteUser</title>
<polygon fill="white" stroke="transparent" points="411,-224 411,-245 481,-245 481,-224 411,-224"/>
<polygon fill="#1b563f" stroke="transparent" points="411,-223.5 411,-244.5 481,-244.5 481,-223.5 411,-223.5"/>
<text text-anchor="start" x="415" y="-231.9" font-family="Roboto" font-size="8.00"> &#160;</text>
<text text-anchor="start" x="420" y="-231.9" font-family="Roboto" font-size="12.00" fill="white">NoteUser</text>
<text text-anchor="start" x="472" y="-231.9" font-family="Roboto" font-size="8.00"> &#160;</text>
</g>
<!-- activity_models_Entry&#45;&gt;note_models_notes_NoteUser -->
<g id="edge6" class="edge">
<title>activity_models_Entry&#45;&gt;note_models_notes_NoteUser</title>
<path fill="none" stroke="black" d="M442.25,-507.94C453.52,-496.48 463.51,-483.41 470,-469 503.73,-394.13 469.49,-292.46 453.39,-252.56"/>
<ellipse fill="black" stroke="black" cx="439.12" cy="-510.99" rx="4" ry="4"/>
<text text-anchor="middle" x="506.5" y="-419.1" font-family="Roboto" font-size="8.00"> note (entry)</text>
</g>
<!-- activity_models_Guest&#45;&gt;activity_models_Activity -->
<g id="edge8" class="edge">
<title>activity_models_Guest&#45;&gt;activity_models_Activity</title>
<path fill="none" stroke="black" d="M341.43,-365.38C336.13,-353.6 330.39,-340.84 324.64,-328.06"/>
<ellipse fill="black" stroke="black" cx="343.2" cy="-369.32" rx="4" ry="4"/>
<text text-anchor="middle" x="354.5" y="-348.6" font-family="Roboto" font-size="8.00"> activity (+)</text>
</g>
<!-- activity_models_Guest&#45;&gt;note_models_notes_NoteUser -->
<g id="edge9" class="edge">
<title>activity_models_Guest&#45;&gt;note_models_notes_NoteUser</title>
<path fill="none" stroke="black" d="M389.66,-365.44C406.3,-327.05 427.51,-278.15 438.55,-252.68"/>
<ellipse fill="black" stroke="black" cx="387.99" cy="-369.3" rx="4" ry="4"/>
<text text-anchor="middle" x="424.5" y="-348.6" font-family="Roboto" font-size="8.00"> inviter (guests)</text>
</g>
<!-- activity_models_GuestTransaction -->
<g id="node5" class="node">
<title>activity_models_GuestTransaction</title>
<polygon fill="white" stroke="transparent" points="350.5,-668 350.5,-717 537.5,-717 537.5,-668 350.5,-668"/>
<polygon fill="#1b563f" stroke="transparent" points="352,-694.5 352,-715.5 537,-715.5 537,-694.5 352,-694.5"/>
<text text-anchor="start" x="386.5" y="-703.5" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="396.5" y="-703.5" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;GuestTransaction &#160;&#160;&#160;</text>
<text text-anchor="start" x="354" y="-687.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="364" y="-687.1" font-family="Roboto" font-weight="bold" font-size="8.00">transaction_ptr</text>
<text text-anchor="start" x="425" y="-687.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="439" y="-687.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="449" y="-687.1" font-family="Roboto" font-weight="bold" font-size="8.00">OneToOneField (id)</text>
<text text-anchor="start" x="525" y="-687.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="354" y="-674.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="364" y="-674.1" font-family="Roboto" font-weight="bold" font-size="8.00">entry</text>
<text text-anchor="start" x="385" y="-674.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="439" y="-674.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="449" y="-674.1" font-family="Roboto" font-weight="bold" font-size="8.00">OneToOneField (id)</text>
<text text-anchor="start" x="525" y="-674.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="350.5,-668 350.5,-717 537.5,-717 537.5,-668 350.5,-668"/>
</g>
<!-- activity_models_GuestTransaction&#45;&gt;activity_models_Entry -->
<g id="edge10" class="edge">
<title>activity_models_GuestTransaction&#45;&gt;activity_models_Entry</title>
<path fill="none" stroke="black" d="M423.89,-663.91C419.84,-658.07 415.69,-651.89 412,-646 404.83,-634.55 397.53,-621.92 390.93,-610.04"/>
<text text-anchor="middle" x="456" y="-635.1" font-family="Roboto" font-size="8.00"> entry (guesttransaction)</text>
</g>
<!-- note_models_transactions_Transaction -->
<g id="node9" class="node">
<title>note_models_transactions_Transaction</title>
<polygon fill="white" stroke="transparent" points="482,-551.5 482,-572.5 562,-572.5 562,-551.5 482,-551.5"/>
<polygon fill="#1b563f" stroke="transparent" points="482,-551 482,-572 562,-572 562,-551 482,-551"/>
<text text-anchor="start" x="486" y="-559.4" font-family="Roboto" font-size="8.00"> &#160;</text>
<text text-anchor="start" x="491" y="-559.4" font-family="Roboto" font-size="12.00" fill="white">Transaction</text>
<text text-anchor="start" x="553" y="-559.4" font-family="Roboto" font-size="8.00"> &#160;</text>
</g>
<!-- activity_models_GuestTransaction&#45;&gt;note_models_transactions_Transaction -->
<g id="edge11" class="edge">
<title>activity_models_GuestTransaction&#45;&gt;note_models_transactions_Transaction</title>
<path fill="none" stroke="black" d="M484.47,-663.95C490.33,-658.55 495.78,-652.52 500,-646 510.86,-629.2 516.38,-607.22 519.17,-590.09"/>
<polygon fill="none" stroke="black" points="522.64,-590.54 520.58,-580.15 515.71,-589.56 522.64,-590.54"/>
<text text-anchor="middle" x="528" y="-639.6" font-family="Roboto" font-size="8.00"> multi&#45;table</text>
<text text-anchor="middle" x="528" y="-630.6" font-family="Roboto" font-size="8.00">inheritance</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 30 KiB

108
docs/_static/img/graphs/logs.svg vendored Normal file
View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.44.1 (0)
-->
<!-- Title: model_graph Pages: 1 -->
<svg width="209pt" height="237pt"
viewBox="0.00 0.00 208.50 237.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 233)">
<title>model_graph</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-233 204.5,-233 204.5,4 -4,4"/>
<!-- logs_models_Changelog -->
<g id="node1" class="node">
<title>logs_models_Changelog</title>
<polygon fill="white" stroke="transparent" points="8,-85 8,-225 181,-225 181,-85 8,-85"/>
<polygon fill="#1b563f" stroke="transparent" points="9.5,-203 9.5,-224 180.5,-224 180.5,-203 9.5,-203"/>
<text text-anchor="start" x="52" y="-212" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="62" y="-212" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;Changelog &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-195.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-195.6" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="29.5" y="-195.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="78.5" y="-195.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="88.5" y="-195.6" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="126.5" y="-195.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-182.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-182.6" font-family="Roboto" font-weight="bold" font-size="8.00">model</text>
<text text-anchor="start" x="46.5" y="-182.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="78.5" y="-182.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="88.5" y="-182.6" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="149.5" y="-182.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-169.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-169.6" font-family="Roboto" font-weight="bold" font-size="8.00">user</text>
<text text-anchor="start" x="39.5" y="-169.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="78.5" y="-169.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="88.5" y="-169.6" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="149.5" y="-169.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-156.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-156.6" font-family="Roboto" font-size="8.00">action</text>
<text text-anchor="start" x="43.5" y="-156.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="78.5" y="-156.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="88.5" y="-156.6" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="123.5" y="-156.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-143.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-143.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">data</text>
<text text-anchor="start" x="37.5" y="-143.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="78.5" y="-143.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="88.5" y="-143.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">TextField</text>
<text text-anchor="start" x="120.5" y="-143.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-130.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-130.6" font-family="Roboto" font-size="8.00">instance_pk</text>
<text text-anchor="start" x="64.5" y="-130.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="78.5" y="-130.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="88.5" y="-130.6" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="123.5" y="-130.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-117.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-117.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">ip</text>
<text text-anchor="start" x="28.5" y="-117.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="78.5" y="-117.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="88.5" y="-117.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">GenericIPAddressField</text>
<text text-anchor="start" x="168.5" y="-117.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-104.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-104.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">previous</text>
<text text-anchor="start" x="51.5" y="-104.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="78.5" y="-104.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="88.5" y="-104.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">TextField</text>
<text text-anchor="start" x="120.5" y="-104.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-91.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-91.6" font-family="Roboto" font-size="8.00">timestamp</text>
<text text-anchor="start" x="58.5" y="-91.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="78.5" y="-91.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="88.5" y="-91.6" font-family="Roboto" font-size="8.00">DateTimeField</text>
<text text-anchor="start" x="140.5" y="-91.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="8,-85 8,-225 181,-225 181,-85 8,-85"/>
</g>
<!-- django_contrib_auth_models_User -->
<g id="node2" class="node">
<title>django_contrib_auth_models_User</title>
<polygon fill="white" stroke="transparent" points="23.5,-7.5 23.5,-28.5 67.5,-28.5 67.5,-7.5 23.5,-7.5"/>
<polygon fill="#1b563f" stroke="transparent" points="23.5,-7 23.5,-28 67.5,-28 67.5,-7 23.5,-7"/>
<text text-anchor="start" x="27.5" y="-15.4" font-family="Roboto" font-size="8.00"> &#160;</text>
<text text-anchor="start" x="32.5" y="-15.4" font-family="Roboto" font-size="12.00" fill="white">User</text>
<text text-anchor="start" x="58.5" y="-15.4" font-family="Roboto" font-size="8.00"> &#160;</text>
</g>
<!-- logs_models_Changelog&#45;&gt;django_contrib_auth_models_User -->
<g id="edge1" class="edge">
<title>logs_models_Changelog&#45;&gt;django_contrib_auth_models_User</title>
<path fill="none" stroke="black" d="M62.09,-73.17C60.86,-69.74 59.65,-66.34 58.5,-63 55.49,-54.26 52.54,-44.41 50.21,-36.25"/>
<ellipse fill="black" stroke="black" cx="63.48" cy="-76.95" rx="4" ry="4"/>
<text text-anchor="middle" x="90.5" y="-56.6" font-family="Roboto" font-size="8.00"> user (changelog)</text>
</g>
<!-- django_contrib_contenttypes_models_ContentType -->
<g id="node3" class="node">
<title>django_contrib_contenttypes_models_ContentType</title>
<polygon fill="white" stroke="transparent" points="101.5,-7.5 101.5,-28.5 187.5,-28.5 187.5,-7.5 101.5,-7.5"/>
<polygon fill="#1b563f" stroke="transparent" points="101.5,-7 101.5,-28 187.5,-28 187.5,-7 101.5,-7"/>
<text text-anchor="start" x="105.5" y="-15.4" font-family="Roboto" font-size="8.00"> &#160;</text>
<text text-anchor="start" x="110.5" y="-15.4" font-family="Roboto" font-size="12.00" fill="white">ContentType</text>
<text text-anchor="start" x="178.5" y="-15.4" font-family="Roboto" font-size="8.00"> &#160;</text>
</g>
<!-- logs_models_Changelog&#45;&gt;django_contrib_contenttypes_models_ContentType -->
<g id="edge2" class="edge">
<title>logs_models_Changelog&#45;&gt;django_contrib_contenttypes_models_ContentType</title>
<path fill="none" stroke="black" d="M124.44,-73.16C129.61,-59.21 134.48,-46.05 138.13,-36.2"/>
<ellipse fill="black" stroke="black" cx="122.94" cy="-77.22" rx="4" ry="4"/>
<text text-anchor="middle" x="165.5" y="-56.6" font-family="Roboto" font-size="8.00"> model (changelog)</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.3 KiB

279
docs/_static/img/graphs/member.svg vendored Normal file
View File

@ -0,0 +1,279 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.44.1 (0)
-->
<!-- Title: model_graph Pages: 1 -->
<svg width="601pt" height="440pt"
viewBox="0.00 0.00 600.50 440.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 436)">
<title>model_graph</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-436 596.5,-436 596.5,4 -4,4"/>
<!-- member_models_Profile -->
<g id="node1" class="node">
<title>member_models_Profile</title>
<polygon fill="white" stroke="transparent" points="8,-210 8,-428 227,-428 227,-210 8,-210"/>
<polygon fill="#1b563f" stroke="transparent" points="9.5,-406 9.5,-427 226.5,-427 226.5,-406 9.5,-406"/>
<text text-anchor="start" x="85.5" y="-415" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="95.5" y="-415" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;Profile &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-398.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-398.6" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="29.5" y="-398.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="115.5" y="-398.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="125.5" y="-398.6" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="163.5" y="-398.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-385.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-385.6" font-family="Roboto" font-weight="bold" font-size="8.00">user</text>
<text text-anchor="start" x="39.5" y="-385.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="115.5" y="-385.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="125.5" y="-385.6" font-family="Roboto" font-weight="bold" font-size="8.00">OneToOneField (id)</text>
<text text-anchor="start" x="201.5" y="-385.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-372.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-372.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">address</text>
<text text-anchor="start" x="49.5" y="-372.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="115.5" y="-372.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="125.5" y="-372.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">CharField</text>
<text text-anchor="start" x="160.5" y="-372.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-359.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-359.6" font-family="Roboto" font-size="8.00">department</text>
<text text-anchor="start" x="63.5" y="-359.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="115.5" y="-359.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="125.5" y="-359.6" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="160.5" y="-359.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-346.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-346.6" font-family="Roboto" font-size="8.00">email_confirmed</text>
<text text-anchor="start" x="80.5" y="-346.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="115.5" y="-346.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="125.5" y="-346.6" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="171.5" y="-346.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-333.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-333.6" font-family="Roboto" font-size="8.00">last_report</text>
<text text-anchor="start" x="59.5" y="-333.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="115.5" y="-333.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="125.5" y="-333.6" font-family="Roboto" font-size="8.00">DateTimeField</text>
<text text-anchor="start" x="177.5" y="-333.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-320.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-320.6" font-family="Roboto" font-size="8.00">ml_art_registration</text>
<text text-anchor="start" x="88.5" y="-320.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="115.5" y="-320.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="125.5" y="-320.6" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="171.5" y="-320.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-307.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-307.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">ml_events_registration</text>
<text text-anchor="start" x="101.5" y="-307.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="115.5" y="-307.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="125.5" y="-307.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">CharField</text>
<text text-anchor="start" x="160.5" y="-307.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-294.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-294.6" font-family="Roboto" font-size="8.00">ml_sport_registration</text>
<text text-anchor="start" x="96.5" y="-294.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="115.5" y="-294.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="125.5" y="-294.6" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="171.5" y="-294.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-281.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-281.6" font-family="Roboto" font-size="8.00">paid</text>
<text text-anchor="start" x="37.5" y="-281.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="115.5" y="-281.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="125.5" y="-281.6" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="171.5" y="-281.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-268.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-268.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">phone_number</text>
<text text-anchor="start" x="76.5" y="-268.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="115.5" y="-268.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="125.5" y="-268.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">PhoneNumberField</text>
<text text-anchor="start" x="195.5" y="-268.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-255.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-255.6" font-family="Roboto" font-size="8.00">promotion</text>
<text text-anchor="start" x="57.5" y="-255.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="115.5" y="-255.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="125.5" y="-255.6" font-family="Roboto" font-size="8.00">PositiveSmallIntegerField</text>
<text text-anchor="start" x="214.5" y="-255.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-242.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-242.6" font-family="Roboto" font-size="8.00">registration_valid</text>
<text text-anchor="start" x="81.5" y="-242.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="115.5" y="-242.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="125.5" y="-242.6" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="171.5" y="-242.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-229.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-229.6" font-family="Roboto" font-size="8.00">report_frequency</text>
<text text-anchor="start" x="82.5" y="-229.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="115.5" y="-229.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="125.5" y="-229.6" font-family="Roboto" font-size="8.00">PositiveSmallIntegerField</text>
<text text-anchor="start" x="214.5" y="-229.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-216.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-216.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">section</text>
<text text-anchor="start" x="46.5" y="-216.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="115.5" y="-216.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="125.5" y="-216.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">CharField</text>
<text text-anchor="start" x="160.5" y="-216.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="8,-210 8,-428 227,-428 227,-210 8,-210"/>
</g>
<!-- django_contrib_auth_models_User -->
<g id="node4" class="node">
<title>django_contrib_auth_models_User</title>
<polygon fill="white" stroke="transparent" points="125.5,-70 125.5,-91 169.5,-91 169.5,-70 125.5,-70"/>
<polygon fill="#1b563f" stroke="transparent" points="125.5,-69.5 125.5,-90.5 169.5,-90.5 169.5,-69.5 125.5,-69.5"/>
<text text-anchor="start" x="129.5" y="-77.9" font-family="Roboto" font-size="8.00"> &#160;</text>
<text text-anchor="start" x="134.5" y="-77.9" font-family="Roboto" font-size="12.00" fill="white">User</text>
<text text-anchor="start" x="160.5" y="-77.9" font-family="Roboto" font-size="8.00"> &#160;</text>
</g>
<!-- member_models_Profile&#45;&gt;django_contrib_auth_models_User -->
<g id="edge1" class="edge">
<title>member_models_Profile&#45;&gt;django_contrib_auth_models_User</title>
<path fill="none" stroke="black" d="M131.71,-205.98C136.98,-164.44 142.38,-121.86 145.3,-98.85"/>
<text text-anchor="middle" x="158.5" y="-181.6" font-family="Roboto" font-size="8.00"> user (profile)</text>
</g>
<!-- member_models_Club -->
<g id="node2" class="node">
<title>member_models_Club</title>
<polygon fill="white" stroke="transparent" points="212,-4 212,-157 421,-157 421,-4 212,-4"/>
<polygon fill="#1b563f" stroke="transparent" points="213.5,-134.5 213.5,-155.5 420.5,-155.5 420.5,-134.5 213.5,-134.5"/>
<text text-anchor="start" x="288.5" y="-143.5" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="298.5" y="-143.5" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;Club &#160;&#160;&#160;</text>
<text text-anchor="start" x="215.5" y="-127.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="225.5" y="-127.1" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="233.5" y="-127.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="328.5" y="-127.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="338.5" y="-127.1" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="376.5" y="-127.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="215.5" y="-114.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="225.5" y="-114.1" font-family="Roboto" font-weight="bold" font-size="8.00" fill="#7b7b7b">parent_club</text>
<text text-anchor="start" x="273.5" y="-114.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="328.5" y="-114.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="338.5" y="-114.1" font-family="Roboto" font-weight="bold" font-size="8.00" fill="#7b7b7b">ForeignKey (id)</text>
<text text-anchor="start" x="399.5" y="-114.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="215.5" y="-101.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="225.5" y="-101.1" font-family="Roboto" font-size="8.00">email</text>
<text text-anchor="start" x="244.5" y="-101.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="328.5" y="-101.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="338.5" y="-101.1" font-family="Roboto" font-size="8.00">EmailField</text>
<text text-anchor="start" x="375.5" y="-101.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="215.5" y="-88.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="225.5" y="-88.1" font-family="Roboto" font-size="8.00" fill="#7b7b7b">membership_duration</text>
<text text-anchor="start" x="304.5" y="-88.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="328.5" y="-88.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="338.5" y="-88.1" font-family="Roboto" font-size="8.00" fill="#7b7b7b">PositiveIntegerField</text>
<text text-anchor="start" x="408.5" y="-88.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="215.5" y="-75.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="225.5" y="-75.1" font-family="Roboto" font-size="8.00" fill="#7b7b7b">membership_end</text>
<text text-anchor="start" x="288.5" y="-75.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="328.5" y="-75.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="338.5" y="-75.1" font-family="Roboto" font-size="8.00" fill="#7b7b7b">DateField</text>
<text text-anchor="start" x="372.5" y="-75.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="215.5" y="-62.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="225.5" y="-62.1" font-family="Roboto" font-size="8.00">membership_fee_paid</text>
<text text-anchor="start" x="305.5" y="-62.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="328.5" y="-62.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="338.5" y="-62.1" font-family="Roboto" font-size="8.00">PositiveIntegerField</text>
<text text-anchor="start" x="408.5" y="-62.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="215.5" y="-49.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="225.5" y="-49.1" font-family="Roboto" font-size="8.00">membership_fee_unpaid</text>
<text text-anchor="start" x="314.5" y="-49.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="328.5" y="-49.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="338.5" y="-49.1" font-family="Roboto" font-size="8.00">PositiveIntegerField</text>
<text text-anchor="start" x="408.5" y="-49.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="215.5" y="-36.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="225.5" y="-36.1" font-family="Roboto" font-size="8.00" fill="#7b7b7b">membership_start</text>
<text text-anchor="start" x="290.5" y="-36.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="328.5" y="-36.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="338.5" y="-36.1" font-family="Roboto" font-size="8.00" fill="#7b7b7b">DateField</text>
<text text-anchor="start" x="372.5" y="-36.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="215.5" y="-23.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="225.5" y="-23.1" font-family="Roboto" font-size="8.00">name</text>
<text text-anchor="start" x="246.5" y="-23.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="328.5" y="-23.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="338.5" y="-23.1" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="373.5" y="-23.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="215.5" y="-10.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="225.5" y="-10.1" font-family="Roboto" font-size="8.00">require_memberships</text>
<text text-anchor="start" x="302.5" y="-10.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="328.5" y="-10.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="338.5" y="-10.1" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="384.5" y="-10.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="212,-4 212,-157 421,-157 421,-4 212,-4"/>
</g>
<!-- member_models_Club&#45;&gt;member_models_Club -->
<g id="edge2" class="edge">
<title>member_models_Club&#45;&gt;member_models_Club</title>
<path fill="none" stroke="black" d="M437.02,-93.04C443.29,-89.95 447,-85.77 447,-80.5 447,-73.33 440.12,-68.17 429.26,-65.04"/>
<ellipse fill="black" stroke="black" cx="433" cy="-94.55" rx="4" ry="4"/>
<text text-anchor="middle" x="480.5" y="-78.6" font-family="Roboto" font-size="8.00"> parent_club (club)</text>
</g>
<!-- member_models_Membership -->
<g id="node3" class="node">
<title>member_models_Membership</title>
<polygon fill="white" stroke="transparent" points="261,-268.5 261,-369.5 418,-369.5 418,-268.5 261,-268.5"/>
<polygon fill="#1b563f" stroke="transparent" points="262.5,-347 262.5,-368 417.5,-368 417.5,-347 262.5,-347"/>
<text text-anchor="start" x="294" y="-356" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="304" y="-356" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;Membership &#160;&#160;&#160;</text>
<text text-anchor="start" x="264.5" y="-339.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="274.5" y="-339.6" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="282.5" y="-339.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="325.5" y="-339.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="335.5" y="-339.6" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="373.5" y="-339.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="264.5" y="-326.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="274.5" y="-326.6" font-family="Roboto" font-weight="bold" font-size="8.00">club</text>
<text text-anchor="start" x="292.5" y="-326.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="325.5" y="-326.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="335.5" y="-326.6" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="396.5" y="-326.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="264.5" y="-313.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="274.5" y="-313.6" font-family="Roboto" font-weight="bold" font-size="8.00">user</text>
<text text-anchor="start" x="292.5" y="-313.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="325.5" y="-313.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="335.5" y="-313.6" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="396.5" y="-313.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="264.5" y="-300.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="274.5" y="-300.6" font-family="Roboto" font-size="8.00">date_end</text>
<text text-anchor="start" x="308.5" y="-300.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="325.5" y="-300.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="335.5" y="-300.6" font-family="Roboto" font-size="8.00">DateField</text>
<text text-anchor="start" x="369.5" y="-300.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="264.5" y="-287.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="274.5" y="-287.6" font-family="Roboto" font-size="8.00">date_start</text>
<text text-anchor="start" x="311.5" y="-287.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="325.5" y="-287.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="335.5" y="-287.6" font-family="Roboto" font-size="8.00">DateField</text>
<text text-anchor="start" x="369.5" y="-287.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="264.5" y="-274.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="274.5" y="-274.6" font-family="Roboto" font-size="8.00">fee</text>
<text text-anchor="start" x="286.5" y="-274.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="325.5" y="-274.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="335.5" y="-274.6" font-family="Roboto" font-size="8.00">PositiveIntegerField</text>
<text text-anchor="start" x="405.5" y="-274.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="261,-268.5 261,-369.5 418,-369.5 418,-268.5 261,-268.5"/>
</g>
<!-- member_models_Membership&#45;&gt;member_models_Club -->
<g id="edge4" class="edge">
<title>member_models_Membership&#45;&gt;member_models_Club</title>
<path fill="none" stroke="black" d="M333.5,-256.33C330.68,-227.34 327.29,-192.43 324.27,-161.45"/>
<ellipse fill="black" stroke="black" cx="333.89" cy="-260.35" rx="4" ry="4"/>
<text text-anchor="middle" x="362.5" y="-181.6" font-family="Roboto" font-size="8.00"> club (membership)</text>
</g>
<!-- member_models_Membership&#45;&gt;django_contrib_auth_models_User -->
<g id="edge3" class="edge">
<title>member_models_Membership&#45;&gt;django_contrib_auth_models_User</title>
<path fill="none" stroke="black" d="M290.49,-258.16C275.79,-240.95 259.35,-222.4 243.5,-206 222.95,-184.74 213.11,-183.97 194.5,-161 178.45,-141.19 164.21,-115.32 155.72,-98.56"/>
<ellipse fill="black" stroke="black" cx="293.24" cy="-261.39" rx="4" ry="4"/>
<text text-anchor="middle" x="261" y="-181.6" font-family="Roboto" font-size="8.00"> user (memberships)</text>
</g>
<!-- permission_models_Role -->
<g id="node5" class="node">
<title>permission_models_Role</title>
<polygon fill="white" stroke="transparent" points="540.5,-70 540.5,-91 584.5,-91 584.5,-70 540.5,-70"/>
<polygon fill="#1b563f" stroke="transparent" points="540.5,-69.5 540.5,-90.5 584.5,-90.5 584.5,-69.5 540.5,-69.5"/>
<text text-anchor="start" x="545" y="-77.9" font-family="Roboto" font-size="8.00"> &#160;</text>
<text text-anchor="start" x="550" y="-77.9" font-family="Roboto" font-size="12.00" fill="white">Role</text>
<text text-anchor="start" x="575" y="-77.9" font-family="Roboto" font-size="8.00"> &#160;</text>
</g>
<!-- member_models_Membership&#45;&gt;permission_models_Role -->
<g id="edge5" class="edge">
<title>member_models_Membership&#45;&gt;permission_models_Role</title>
<path fill="none" stroke="black" d="M422.13,-259.45C456.46,-232.28 494.89,-197.84 523.5,-161 536.38,-144.41 546.62,-122.88 553.37,-106.41"/>
<ellipse fill="black" stroke="black" cx="418.91" cy="-261.97" rx="4" ry="4"/>
<ellipse fill="black" stroke="black" cx="554.93" cy="-102.49" rx="4" ry="4"/>
<text text-anchor="middle" x="542.5" y="-181.6" font-family="Roboto" font-size="8.00"> roles (membership)</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 26 KiB

588
docs/_static/img/graphs/note.svg vendored Normal file
View File

@ -0,0 +1,588 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.44.1 (0)
-->
<!-- Title: model_graph Pages: 1 -->
<svg width="1306pt" height="872pt"
viewBox="0.00 0.00 1306.00 872.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 868)">
<title>model_graph</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-868 1302,-868 1302,4 -4,4"/>
<!-- polymorphic_models_PolymorphicModel -->
<g id="node1" class="node">
<title>polymorphic_models_PolymorphicModel</title>
<polygon fill="white" stroke="transparent" points="254,-85 254,-121 441,-121 441,-85 254,-85"/>
<polygon fill="#1b563f" stroke="transparent" points="255.5,-99 255.5,-120 440.5,-120 440.5,-99 255.5,-99"/>
<text text-anchor="start" x="286.5" y="-108" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="296.5" y="-108" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;PolymorphicModel &#160;&#160;&#160;</text>
<text text-anchor="start" x="257.5" y="-91.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="267.5" y="-91.6" font-family="Roboto" font-weight="bold" font-size="8.00">polymorphic_ctype</text>
<text text-anchor="start" x="343.5" y="-91.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="357.5" y="-91.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="367.5" y="-91.6" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="428.5" y="-91.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="254,-85 254,-121 441,-121 441,-85 254,-85"/>
</g>
<!-- django_contrib_contenttypes_models_ContentType -->
<g id="node13" class="node">
<title>django_contrib_contenttypes_models_ContentType</title>
<polygon fill="white" stroke="transparent" points="304.5,-7.5 304.5,-28.5 390.5,-28.5 390.5,-7.5 304.5,-7.5"/>
<polygon fill="#1b563f" stroke="transparent" points="304.5,-7 304.5,-28 390.5,-28 390.5,-7 304.5,-7"/>
<text text-anchor="start" x="308.5" y="-15.4" font-family="Roboto" font-size="8.00"> &#160;</text>
<text text-anchor="start" x="313.5" y="-15.4" font-family="Roboto" font-size="12.00" fill="white">ContentType</text>
<text text-anchor="start" x="381.5" y="-15.4" font-family="Roboto" font-size="8.00"> &#160;</text>
</g>
<!-- polymorphic_models_PolymorphicModel&#45;&gt;django_contrib_contenttypes_models_ContentType -->
<g id="edge1" class="edge">
<title>polymorphic_models_PolymorphicModel&#45;&gt;django_contrib_contenttypes_models_ContentType</title>
<path fill="none" stroke="black" d="M347.5,-72.49C347.5,-60.3 347.5,-46.6 347.5,-36.12"/>
<ellipse fill="black" stroke="black" cx="347.5" cy="-76.63" rx="4" ry="4"/>
<text text-anchor="middle" x="463" y="-56.6" font-family="Roboto" font-size="8.00"> polymorphic_ctype (polymorphic_%(app_label)s.%(class)s_set+)</text>
</g>
<!-- note_models_notes_Note -->
<g id="node2" class="node">
<title>note_models_notes_Note</title>
<polygon fill="white" stroke="transparent" points="366,-183 366,-319 553,-319 553,-183 366,-183"/>
<polygon fill="#1b563f" stroke="transparent" points="367.5,-288 367.5,-318 552.5,-318 552.5,-288 367.5,-288"/>
<text text-anchor="start" x="438" y="-306" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="448" y="-306" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;Note</text>
<text text-anchor="start" x="402.5" y="-296" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white">&lt;</text>
<text text-anchor="start" x="409.5" y="-296" font-family="Roboto" font-weight="bold" font-style="italic" font-size="10.00" fill="white">PolymorphicModel</text>
<text text-anchor="start" x="498.5" y="-296" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white">&gt; &#160;&#160;&#160;</text>
<text text-anchor="start" x="369.5" y="-280.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="379.5" y="-280.6" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="387.5" y="-280.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="469.5" y="-280.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="479.5" y="-280.6" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="517.5" y="-280.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="369.5" y="-267.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="379.5" y="-267.6" font-family="Roboto" font-weight="bold" font-style="italic" font-size="8.00">polymorphic_ctype</text>
<text text-anchor="start" x="455.5" y="-267.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="469.5" y="-267.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="479.5" y="-267.6" font-family="Roboto" font-weight="bold" font-style="italic" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="540.5" y="-267.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="369.5" y="-254.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="379.5" y="-254.6" font-family="Roboto" font-size="8.00">balance</text>
<text text-anchor="start" x="407.5" y="-254.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="469.5" y="-254.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="479.5" y="-254.6" font-family="Roboto" font-size="8.00">BigIntegerField</text>
<text text-anchor="start" x="533.5" y="-254.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="369.5" y="-241.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="379.5" y="-241.6" font-family="Roboto" font-size="8.00">created_at</text>
<text text-anchor="start" x="417.5" y="-241.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="469.5" y="-241.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="479.5" y="-241.6" font-family="Roboto" font-size="8.00">DateTimeField</text>
<text text-anchor="start" x="531.5" y="-241.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="369.5" y="-228.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="379.5" y="-228.6" font-family="Roboto" font-size="8.00">display_image</text>
<text text-anchor="start" x="430.5" y="-228.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="469.5" y="-228.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="479.5" y="-228.6" font-family="Roboto" font-size="8.00">ImageField</text>
<text text-anchor="start" x="519.5" y="-228.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="369.5" y="-215.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="379.5" y="-215.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">inactivity_reason</text>
<text text-anchor="start" x="437.5" y="-215.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="469.5" y="-215.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="479.5" y="-215.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">CharField</text>
<text text-anchor="start" x="514.5" y="-215.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="369.5" y="-202.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="379.5" y="-202.6" font-family="Roboto" font-size="8.00">is_active</text>
<text text-anchor="start" x="410.5" y="-202.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="469.5" y="-202.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="479.5" y="-202.6" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="525.5" y="-202.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="369.5" y="-189.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="379.5" y="-189.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">last_negative</text>
<text text-anchor="start" x="426.5" y="-189.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="469.5" y="-189.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="479.5" y="-189.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">DateTimeField</text>
<text text-anchor="start" x="531.5" y="-189.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="366,-183 366,-319 553,-319 553,-183 366,-183"/>
</g>
<!-- note_models_notes_Note&#45;&gt;polymorphic_models_PolymorphicModel -->
<g id="edge2" class="edge">
<title>note_models_notes_Note&#45;&gt;polymorphic_models_PolymorphicModel</title>
<path fill="none" stroke="black" d="M404.81,-178.71C392.51,-162.68 380.13,-146.54 370.04,-133.38"/>
<polygon fill="none" stroke="black" points="372.62,-131 363.76,-125.2 367.07,-135.26 372.62,-131"/>
<text text-anchor="middle" x="410.5" y="-154.6" font-family="Roboto" font-size="8.00"> abstract</text>
<text text-anchor="middle" x="410.5" y="-145.6" font-family="Roboto" font-size="8.00">inheritance</text>
</g>
<!-- note_models_notes_NoteUser -->
<g id="node3" class="node">
<title>note_models_notes_NoteUser</title>
<polygon fill="white" stroke="transparent" points="8,-450.5 8,-499.5 167,-499.5 167,-450.5 8,-450.5"/>
<polygon fill="#1b563f" stroke="transparent" points="9.5,-477 9.5,-498 166.5,-498 166.5,-477 9.5,-477"/>
<text text-anchor="start" x="49" y="-486" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="59" y="-486" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;NoteUser &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-469.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-469.6" font-family="Roboto" font-weight="bold" font-size="8.00">note_ptr</text>
<text text-anchor="start" x="54.5" y="-469.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="68.5" y="-469.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="78.5" y="-469.6" font-family="Roboto" font-weight="bold" font-size="8.00">OneToOneField (id)</text>
<text text-anchor="start" x="154.5" y="-469.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11.5" y="-456.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21.5" y="-456.6" font-family="Roboto" font-weight="bold" font-size="8.00">user</text>
<text text-anchor="start" x="39.5" y="-456.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="68.5" y="-456.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="78.5" y="-456.6" font-family="Roboto" font-weight="bold" font-size="8.00">OneToOneField (id)</text>
<text text-anchor="start" x="154.5" y="-456.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="8,-450.5 8,-499.5 167,-499.5 167,-450.5 8,-450.5"/>
</g>
<!-- note_models_notes_NoteUser&#45;&gt;note_models_notes_Note -->
<g id="edge4" class="edge">
<title>note_models_notes_NoteUser&#45;&gt;note_models_notes_Note</title>
<path fill="none" stroke="black" d="M109.11,-446.28C127.2,-424.73 154.77,-395.49 184.5,-377 247.87,-337.59 275.92,-354.68 343.5,-323 345.12,-322.24 346.74,-321.47 348.37,-320.68"/>
<polygon fill="none" stroke="black" points="350.34,-323.6 357.71,-315.99 347.2,-317.34 350.34,-323.6"/>
<text text-anchor="middle" x="311.5" y="-352.6" font-family="Roboto" font-size="8.00"> multi&#45;table</text>
<text text-anchor="middle" x="311.5" y="-343.6" font-family="Roboto" font-size="8.00">inheritance</text>
</g>
<!-- django_contrib_auth_models_User -->
<g id="node14" class="node">
<title>django_contrib_auth_models_User</title>
<polygon fill="white" stroke="transparent" points="65.5,-240.5 65.5,-261.5 109.5,-261.5 109.5,-240.5 65.5,-240.5"/>
<polygon fill="#1b563f" stroke="transparent" points="65.5,-240 65.5,-261 109.5,-261 109.5,-240 65.5,-240"/>
<text text-anchor="start" x="69.5" y="-248.4" font-family="Roboto" font-size="8.00"> &#160;</text>
<text text-anchor="start" x="74.5" y="-248.4" font-family="Roboto" font-size="12.00" fill="white">User</text>
<text text-anchor="start" x="100.5" y="-248.4" font-family="Roboto" font-size="8.00"> &#160;</text>
</g>
<!-- note_models_notes_NoteUser&#45;&gt;django_contrib_auth_models_User -->
<g id="edge3" class="edge">
<title>note_models_notes_NoteUser&#45;&gt;django_contrib_auth_models_User</title>
<path fill="none" stroke="black" d="M87.5,-446.33C87.5,-399.84 87.5,-307.38 87.5,-269.15"/>
<text text-anchor="middle" x="109" y="-348.1" font-family="Roboto" font-size="8.00"> user (note)</text>
</g>
<!-- note_models_notes_NoteClub -->
<g id="node4" class="node">
<title>note_models_notes_NoteClub</title>
<polygon fill="white" stroke="transparent" points="1131,-450.5 1131,-499.5 1290,-499.5 1290,-450.5 1131,-450.5"/>
<polygon fill="#1b563f" stroke="transparent" points="1132.5,-477 1132.5,-498 1289.5,-498 1289.5,-477 1132.5,-477"/>
<text text-anchor="start" x="1171.5" y="-486" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1181.5" y="-486" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;NoteClub &#160;&#160;&#160;</text>
<text text-anchor="start" x="1134.5" y="-469.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1144.5" y="-469.6" font-family="Roboto" font-weight="bold" font-size="8.00">note_ptr</text>
<text text-anchor="start" x="1177.5" y="-469.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1191.5" y="-469.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1201.5" y="-469.6" font-family="Roboto" font-weight="bold" font-size="8.00">OneToOneField (id)</text>
<text text-anchor="start" x="1277.5" y="-469.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1134.5" y="-456.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1144.5" y="-456.6" font-family="Roboto" font-weight="bold" font-size="8.00">club</text>
<text text-anchor="start" x="1162.5" y="-456.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1191.5" y="-456.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1201.5" y="-456.6" font-family="Roboto" font-weight="bold" font-size="8.00">OneToOneField (id)</text>
<text text-anchor="start" x="1277.5" y="-456.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="1131,-450.5 1131,-499.5 1290,-499.5 1290,-450.5 1131,-450.5"/>
</g>
<!-- note_models_notes_NoteClub&#45;&gt;note_models_notes_Note -->
<g id="edge6" class="edge">
<title>note_models_notes_NoteClub&#45;&gt;note_models_notes_Note</title>
<path fill="none" stroke="black" d="M1190.62,-446.48C1172.94,-424.15 1145.07,-393.72 1113.5,-377 939.22,-284.69 706.77,-259.9 571.09,-253.63"/>
<polygon fill="none" stroke="black" points="571.23,-250.13 561.09,-253.2 570.92,-257.13 571.23,-250.13"/>
<text text-anchor="middle" x="1084.5" y="-352.6" font-family="Roboto" font-size="8.00"> multi&#45;table</text>
<text text-anchor="middle" x="1084.5" y="-343.6" font-family="Roboto" font-size="8.00">inheritance</text>
</g>
<!-- member_models_Club -->
<g id="node15" class="node">
<title>member_models_Club</title>
<polygon fill="white" stroke="transparent" points="1188.5,-240.5 1188.5,-261.5 1232.5,-261.5 1232.5,-240.5 1188.5,-240.5"/>
<polygon fill="#1b563f" stroke="transparent" points="1188.5,-240 1188.5,-261 1232.5,-261 1232.5,-240 1188.5,-240"/>
<text text-anchor="start" x="1192.5" y="-248.4" font-family="Roboto" font-size="8.00"> &#160;</text>
<text text-anchor="start" x="1197.5" y="-248.4" font-family="Roboto" font-size="12.00" fill="white">Club</text>
<text text-anchor="start" x="1223.5" y="-248.4" font-family="Roboto" font-size="8.00"> &#160;</text>
</g>
<!-- note_models_notes_NoteClub&#45;&gt;member_models_Club -->
<g id="edge5" class="edge">
<title>note_models_notes_NoteClub&#45;&gt;member_models_Club</title>
<path fill="none" stroke="black" d="M1210.5,-446.33C1210.5,-399.84 1210.5,-307.38 1210.5,-269.15"/>
<text text-anchor="middle" x="1231" y="-348.1" font-family="Roboto" font-size="8.00"> club (note)</text>
</g>
<!-- note_models_notes_NoteSpecial -->
<g id="node5" class="node">
<title>note_models_notes_NoteSpecial</title>
<polygon fill="white" stroke="transparent" points="926.5,-450.5 926.5,-499.5 1096.5,-499.5 1096.5,-450.5 926.5,-450.5"/>
<polygon fill="#1b563f" stroke="transparent" points="927.5,-477 927.5,-498 1095.5,-498 1095.5,-477 927.5,-477"/>
<text text-anchor="start" x="966" y="-486" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="976" y="-486" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;NoteSpecial &#160;&#160;&#160;</text>
<text text-anchor="start" x="929.5" y="-469.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="939.5" y="-469.6" font-family="Roboto" font-weight="bold" font-size="8.00">note_ptr</text>
<text text-anchor="start" x="972.5" y="-469.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="997.5" y="-469.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1007.5" y="-469.6" font-family="Roboto" font-weight="bold" font-size="8.00">OneToOneField (id)</text>
<text text-anchor="start" x="1083.5" y="-469.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="929.5" y="-456.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="939.5" y="-456.6" font-family="Roboto" font-size="8.00">special_type</text>
<text text-anchor="start" x="983.5" y="-456.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="997.5" y="-456.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1007.5" y="-456.6" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="1042.5" y="-456.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="926.5,-450.5 926.5,-499.5 1096.5,-499.5 1096.5,-450.5 926.5,-450.5"/>
</g>
<!-- note_models_notes_NoteSpecial&#45;&gt;note_models_notes_Note -->
<g id="edge7" class="edge">
<title>note_models_notes_NoteSpecial&#45;&gt;note_models_notes_Note</title>
<path fill="none" stroke="black" d="M989.16,-446.3C970.14,-424.47 940.97,-394.83 909.5,-377 803.05,-316.67 665.72,-284.03 570.92,-267.4"/>
<polygon fill="none" stroke="black" points="571.47,-263.94 561.02,-265.69 570.28,-270.84 571.47,-263.94"/>
<text text-anchor="middle" x="884.5" y="-352.6" font-family="Roboto" font-size="8.00"> multi&#45;table</text>
<text text-anchor="middle" x="884.5" y="-343.6" font-family="Roboto" font-size="8.00">inheritance</text>
</g>
<!-- note_models_notes_Alias -->
<g id="node6" class="node">
<title>note_models_notes_Alias</title>
<polygon fill="white" stroke="transparent" points="717,-437.5 717,-512.5 892,-512.5 892,-437.5 717,-437.5"/>
<polygon fill="#1b563f" stroke="transparent" points="718.5,-490 718.5,-511 891.5,-511 891.5,-490 718.5,-490"/>
<text text-anchor="start" x="775.5" y="-499" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="785.5" y="-499" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;Alias &#160;&#160;&#160;</text>
<text text-anchor="start" x="720.5" y="-482.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="730.5" y="-482.6" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="738.5" y="-482.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="808.5" y="-482.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="818.5" y="-482.6" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="856.5" y="-482.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="720.5" y="-469.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="730.5" y="-469.6" font-family="Roboto" font-weight="bold" font-size="8.00">note</text>
<text text-anchor="start" x="748.5" y="-469.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="808.5" y="-469.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="818.5" y="-469.6" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="879.5" y="-469.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="720.5" y="-456.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="730.5" y="-456.6" font-family="Roboto" font-size="8.00">name</text>
<text text-anchor="start" x="751.5" y="-456.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="808.5" y="-456.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="818.5" y="-456.6" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="853.5" y="-456.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="720.5" y="-443.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="730.5" y="-443.6" font-family="Roboto" font-size="8.00">normalized_name</text>
<text text-anchor="start" x="794.5" y="-443.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="808.5" y="-443.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="818.5" y="-443.6" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="853.5" y="-443.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="717,-437.5 717,-512.5 892,-512.5 892,-437.5 717,-437.5"/>
</g>
<!-- note_models_notes_Alias&#45;&gt;note_models_notes_Note -->
<g id="edge8" class="edge">
<title>note_models_notes_Alias&#45;&gt;note_models_notes_Note</title>
<path fill="none" stroke="black" d="M759.38,-427.39C741.62,-410.4 720.47,-391.75 699.5,-377 656.46,-346.73 605.15,-319.02 561.03,-297.42"/>
<ellipse fill="black" stroke="black" cx="762.4" cy="-430.3" rx="4" ry="4"/>
<text text-anchor="middle" x="691" y="-348.1" font-family="Roboto" font-size="8.00"> note (alias)</text>
</g>
<!-- note_models_transactions_TemplateCategory -->
<g id="node7" class="node">
<title>note_models_transactions_TemplateCategory</title>
<polygon fill="white" stroke="transparent" points="552,-450.5 552,-499.5 683,-499.5 683,-450.5 552,-450.5"/>
<polygon fill="#1b563f" stroke="transparent" points="553.5,-477 553.5,-498 682.5,-498 682.5,-477 553.5,-477"/>
<text text-anchor="start" x="558.5" y="-486" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="568.5" y="-486" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;TemplateCategory &#160;&#160;&#160;</text>
<text text-anchor="start" x="555.5" y="-469.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="565.5" y="-469.6" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="573.5" y="-469.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="611.5" y="-469.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="621.5" y="-469.6" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="659.5" y="-469.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="555.5" y="-456.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="565.5" y="-456.6" font-family="Roboto" font-size="8.00">name</text>
<text text-anchor="start" x="586.5" y="-456.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="611.5" y="-456.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="621.5" y="-456.6" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="656.5" y="-456.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="552,-450.5 552,-499.5 683,-499.5 683,-450.5 552,-450.5"/>
</g>
<!-- note_models_transactions_TransactionTemplate -->
<g id="node8" class="node">
<title>note_models_transactions_TransactionTemplate</title>
<polygon fill="white" stroke="transparent" points="625,-631 625,-758 806,-758 806,-631 625,-631"/>
<polygon fill="#1b563f" stroke="transparent" points="626.5,-735.5 626.5,-756.5 805.5,-756.5 805.5,-735.5 626.5,-735.5"/>
<text text-anchor="start" x="651" y="-744.5" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="661" y="-744.5" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;TransactionTemplate &#160;&#160;&#160;</text>
<text text-anchor="start" x="628.5" y="-728.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="638.5" y="-728.1" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="646.5" y="-728.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="698.5" y="-728.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="708.5" y="-728.1" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="746.5" y="-728.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="628.5" y="-715.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="638.5" y="-715.1" font-family="Roboto" font-weight="bold" font-size="8.00">category</text>
<text text-anchor="start" x="672.5" y="-715.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="698.5" y="-715.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="708.5" y="-715.1" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="769.5" y="-715.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="628.5" y="-702.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="638.5" y="-702.1" font-family="Roboto" font-weight="bold" font-size="8.00">destination</text>
<text text-anchor="start" x="684.5" y="-702.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="698.5" y="-702.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="708.5" y="-702.1" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (note_ptr)</text>
<text text-anchor="start" x="793.5" y="-702.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="628.5" y="-689.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="638.5" y="-689.1" font-family="Roboto" font-size="8.00">amount</text>
<text text-anchor="start" x="666.5" y="-689.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="698.5" y="-689.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="708.5" y="-689.1" font-family="Roboto" font-size="8.00">PositiveIntegerField</text>
<text text-anchor="start" x="778.5" y="-689.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="628.5" y="-676.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="638.5" y="-676.1" font-family="Roboto" font-size="8.00" fill="#7b7b7b">description</text>
<text text-anchor="start" x="677.5" y="-676.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="698.5" y="-676.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="708.5" y="-676.1" font-family="Roboto" font-size="8.00" fill="#7b7b7b">CharField</text>
<text text-anchor="start" x="743.5" y="-676.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="628.5" y="-663.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="638.5" y="-663.1" font-family="Roboto" font-size="8.00">display</text>
<text text-anchor="start" x="663.5" y="-663.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="698.5" y="-663.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="708.5" y="-663.1" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="754.5" y="-663.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="628.5" y="-650.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="638.5" y="-650.1" font-family="Roboto" font-size="8.00">highlighted</text>
<text text-anchor="start" x="677.5" y="-650.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="698.5" y="-650.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="708.5" y="-650.1" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="754.5" y="-650.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="628.5" y="-637.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="638.5" y="-637.1" font-family="Roboto" font-size="8.00">name</text>
<text text-anchor="start" x="659.5" y="-637.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="698.5" y="-637.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="708.5" y="-637.1" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="743.5" y="-637.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="625,-631 625,-758 806,-758 806,-631 625,-631"/>
</g>
<!-- note_models_transactions_TransactionTemplate&#45;&gt;note_models_notes_NoteClub -->
<g id="edge9" class="edge">
<title>note_models_transactions_TransactionTemplate&#45;&gt;note_models_notes_NoteClub</title>
<path fill="none" stroke="black" d="M822.23,-675.98C905.89,-658.86 1022.9,-627.27 1113.5,-573 1143.74,-554.89 1171.43,-525.3 1189.42,-503.55"/>
<ellipse fill="black" stroke="black" cx="818.16" cy="-676.8" rx="4" ry="4"/>
<text text-anchor="middle" x="1100.5" y="-598.1" font-family="Roboto" font-size="8.00"> destination (+)</text>
</g>
<!-- note_models_transactions_TransactionTemplate&#45;&gt;note_models_transactions_TemplateCategory -->
<g id="edge10" class="edge">
<title>note_models_transactions_TransactionTemplate&#45;&gt;note_models_transactions_TemplateCategory</title>
<path fill="none" stroke="black" d="M682.12,-619.41C664.15,-579.54 643.06,-532.72 629.98,-503.71"/>
<ellipse fill="black" stroke="black" cx="683.79" cy="-623.12" rx="4" ry="4"/>
<text text-anchor="middle" x="713.5" y="-598.1" font-family="Roboto" font-size="8.00"> category (templates)</text>
</g>
<!-- note_models_transactions_Transaction -->
<g id="node9" class="node">
<title>note_models_transactions_Transaction</title>
<polygon fill="white" stroke="transparent" points="201.5,-381 201.5,-569 397.5,-569 397.5,-381 201.5,-381"/>
<polygon fill="#1b563f" stroke="transparent" points="202.5,-538 202.5,-568 396.5,-568 396.5,-538 202.5,-538"/>
<text text-anchor="start" x="261" y="-556" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="271" y="-556" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;Transaction</text>
<text text-anchor="start" x="242" y="-546" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white">&lt;</text>
<text text-anchor="start" x="249" y="-546" font-family="Roboto" font-weight="bold" font-style="italic" font-size="10.00" fill="white">PolymorphicModel</text>
<text text-anchor="start" x="338" y="-546" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white">&gt; &#160;&#160;&#160;</text>
<text text-anchor="start" x="204.5" y="-530.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="214.5" y="-530.6" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="222.5" y="-530.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="304.5" y="-530.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="314.5" y="-530.6" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="352.5" y="-530.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="204.5" y="-517.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="214.5" y="-517.6" font-family="Roboto" font-weight="bold" font-size="8.00">destination</text>
<text text-anchor="start" x="260.5" y="-517.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="304.5" y="-517.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="314.5" y="-517.6" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="375.5" y="-517.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="204.5" y="-504.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="214.5" y="-504.6" font-family="Roboto" font-weight="bold" font-style="italic" font-size="8.00">polymorphic_ctype</text>
<text text-anchor="start" x="290.5" y="-504.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="304.5" y="-504.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="314.5" y="-504.6" font-family="Roboto" font-weight="bold" font-style="italic" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="375.5" y="-504.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="204.5" y="-491.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="214.5" y="-491.6" font-family="Roboto" font-weight="bold" font-size="8.00">source</text>
<text text-anchor="start" x="242.5" y="-491.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="304.5" y="-491.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="314.5" y="-491.6" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="375.5" y="-491.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="204.5" y="-478.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="214.5" y="-478.6" font-family="Roboto" font-size="8.00">amount</text>
<text text-anchor="start" x="242.5" y="-478.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="304.5" y="-478.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="314.5" y="-478.6" font-family="Roboto" font-size="8.00">PositiveIntegerField</text>
<text text-anchor="start" x="384.5" y="-478.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="204.5" y="-465.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="214.5" y="-465.6" font-family="Roboto" font-size="8.00">created_at</text>
<text text-anchor="start" x="252.5" y="-465.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="304.5" y="-465.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="314.5" y="-465.6" font-family="Roboto" font-size="8.00">DateTimeField</text>
<text text-anchor="start" x="366.5" y="-465.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="204.5" y="-452.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="214.5" y="-452.6" font-family="Roboto" font-size="8.00">destination_alias</text>
<text text-anchor="start" x="273.5" y="-452.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="304.5" y="-452.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="314.5" y="-452.6" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="349.5" y="-452.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="204.5" y="-439.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="214.5" y="-439.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">invalidity_reason</text>
<text text-anchor="start" x="272.5" y="-439.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="304.5" y="-439.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="314.5" y="-439.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">CharField</text>
<text text-anchor="start" x="349.5" y="-439.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="204.5" y="-426.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="214.5" y="-426.6" font-family="Roboto" font-size="8.00">quantity</text>
<text text-anchor="start" x="242.5" y="-426.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="304.5" y="-426.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="314.5" y="-426.6" font-family="Roboto" font-size="8.00">PositiveIntegerField</text>
<text text-anchor="start" x="384.5" y="-426.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="204.5" y="-413.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="214.5" y="-413.6" font-family="Roboto" font-size="8.00">reason</text>
<text text-anchor="start" x="239.5" y="-413.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="304.5" y="-413.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="314.5" y="-413.6" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="349.5" y="-413.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="204.5" y="-400.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="214.5" y="-400.6" font-family="Roboto" font-size="8.00">source_alias</text>
<text text-anchor="start" x="259.5" y="-400.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="304.5" y="-400.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="314.5" y="-400.6" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="349.5" y="-400.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="204.5" y="-387.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="214.5" y="-387.6" font-family="Roboto" font-size="8.00">valid</text>
<text text-anchor="start" x="230.5" y="-387.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="304.5" y="-387.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="314.5" y="-387.6" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="360.5" y="-387.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="201.5,-381 201.5,-569 397.5,-569 397.5,-381 201.5,-381"/>
</g>
<!-- note_models_transactions_Transaction&#45;&gt;polymorphic_models_PolymorphicModel -->
<g id="edge13" class="edge">
<title>note_models_transactions_Transaction&#45;&gt;polymorphic_models_PolymorphicModel</title>
<path fill="none" stroke="black" d="M291.68,-376.8C289.64,-318.52 291.7,-243.46 308.5,-179 312.59,-163.31 320.42,-147.19 327.99,-133.93"/>
<polygon fill="none" stroke="black" points="331.05,-135.64 333.14,-125.26 325.03,-132.07 331.05,-135.64"/>
<text text-anchor="middle" x="328.5" y="-253.6" font-family="Roboto" font-size="8.00"> abstract</text>
<text text-anchor="middle" x="328.5" y="-244.6" font-family="Roboto" font-size="8.00">inheritance</text>
</g>
<!-- note_models_transactions_Transaction&#45;&gt;note_models_notes_Note -->
<g id="edge11" class="edge">
<title>note_models_transactions_Transaction&#45;&gt;note_models_notes_Note</title>
<path fill="none" stroke="black" d="M407.37,-370.47C410.2,-366.68 412.92,-362.85 415.5,-359 422.87,-347.98 429.37,-335.54 434.95,-323.13"/>
<ellipse fill="black" stroke="black" cx="404.93" cy="-373.64" rx="4" ry="4"/>
<text text-anchor="middle" x="445.5" y="-348.1" font-family="Roboto" font-size="8.00"> source (+)</text>
</g>
<!-- note_models_transactions_Transaction&#45;&gt;note_models_notes_Note -->
<g id="edge12" class="edge">
<title>note_models_transactions_Transaction&#45;&gt;note_models_notes_Note</title>
<path fill="none" stroke="black" d="M339.68,-369.46C345.09,-359.49 351.03,-349.83 357.5,-341 361.94,-334.93 366.87,-328.99 372.09,-323.24"/>
<ellipse fill="black" stroke="black" cx="337.7" cy="-373.21" rx="4" ry="4"/>
<text text-anchor="middle" x="384.5" y="-348.1" font-family="Roboto" font-size="8.00"> destination (+)</text>
</g>
<!-- note_models_transactions_RecurrentTransaction -->
<g id="node10" class="node">
<title>note_models_transactions_RecurrentTransaction</title>
<polygon fill="white" stroke="transparent" points="39,-811 39,-860 226,-860 226,-811 39,-811"/>
<polygon fill="#1b563f" stroke="transparent" points="40.5,-837.5 40.5,-858.5 225.5,-858.5 225.5,-837.5 40.5,-837.5"/>
<text text-anchor="start" x="66" y="-846.5" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="76" y="-846.5" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;RecurrentTransaction &#160;&#160;&#160;</text>
<text text-anchor="start" x="42.5" y="-830.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="52.5" y="-830.1" font-family="Roboto" font-weight="bold" font-size="8.00">transaction_ptr</text>
<text text-anchor="start" x="113.5" y="-830.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="127.5" y="-830.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="137.5" y="-830.1" font-family="Roboto" font-weight="bold" font-size="8.00">OneToOneField (id)</text>
<text text-anchor="start" x="213.5" y="-830.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="42.5" y="-817.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="52.5" y="-817.1" font-family="Roboto" font-weight="bold" font-size="8.00">template</text>
<text text-anchor="start" x="86.5" y="-817.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="127.5" y="-817.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="137.5" y="-817.1" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="198.5" y="-817.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="39,-811 39,-860 226,-860 226,-811 39,-811"/>
</g>
<!-- note_models_transactions_RecurrentTransaction&#45;&gt;note_models_transactions_TransactionTemplate -->
<g id="edge14" class="edge">
<title>note_models_transactions_RecurrentTransaction&#45;&gt;note_models_transactions_TransactionTemplate</title>
<path fill="none" stroke="black" d="M242.27,-830.15C340.58,-823.38 487.34,-806.09 607.5,-762 610.6,-760.86 613.71,-759.63 616.81,-758.32"/>
<ellipse fill="black" stroke="black" cx="238.09" cy="-830.43" rx="4" ry="4"/>
<text text-anchor="middle" x="601.5" y="-782.6" font-family="Roboto" font-size="8.00"> template (recurrenttransaction)</text>
</g>
<!-- note_models_transactions_RecurrentTransaction&#45;&gt;note_models_transactions_Transaction -->
<g id="edge15" class="edge">
<title>note_models_transactions_RecurrentTransaction&#45;&gt;note_models_transactions_Transaction</title>
<path fill="none" stroke="black" d="M124.08,-806.79C113.13,-765.51 98.42,-686.36 125.5,-627 127.55,-622.52 153.83,-599.09 185.37,-571.97"/>
<polygon fill="none" stroke="black" points="187.73,-574.55 193.05,-565.39 183.18,-569.24 187.73,-574.55"/>
<text text-anchor="middle" x="145.5" y="-697.1" font-family="Roboto" font-size="8.00"> multi&#45;table</text>
<text text-anchor="middle" x="145.5" y="-688.1" font-family="Roboto" font-size="8.00">inheritance</text>
</g>
<!-- note_models_transactions_SpecialTransaction -->
<g id="node11" class="node">
<title>note_models_transactions_SpecialTransaction</title>
<polygon fill="white" stroke="transparent" points="183,-657 183,-732 370,-732 370,-657 183,-657"/>
<polygon fill="#1b563f" stroke="transparent" points="184.5,-709.5 184.5,-730.5 369.5,-730.5 369.5,-709.5 184.5,-709.5"/>
<text text-anchor="start" x="215.5" y="-718.5" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="225.5" y="-718.5" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;SpecialTransaction &#160;&#160;&#160;</text>
<text text-anchor="start" x="186.5" y="-702.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="196.5" y="-702.1" font-family="Roboto" font-weight="bold" font-size="8.00">transaction_ptr</text>
<text text-anchor="start" x="257.5" y="-702.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="271.5" y="-702.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="281.5" y="-702.1" font-family="Roboto" font-weight="bold" font-size="8.00">OneToOneField (id)</text>
<text text-anchor="start" x="357.5" y="-702.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="186.5" y="-689.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="196.5" y="-689.1" font-family="Roboto" font-size="8.00" fill="#7b7b7b">bank</text>
<text text-anchor="start" x="214.5" y="-689.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="271.5" y="-689.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="281.5" y="-689.1" font-family="Roboto" font-size="8.00" fill="#7b7b7b">CharField</text>
<text text-anchor="start" x="316.5" y="-689.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="186.5" y="-676.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="196.5" y="-676.1" font-family="Roboto" font-size="8.00">first_name</text>
<text text-anchor="start" x="234.5" y="-676.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="271.5" y="-676.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="281.5" y="-676.1" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="316.5" y="-676.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="186.5" y="-663.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="196.5" y="-663.1" font-family="Roboto" font-size="8.00">last_name</text>
<text text-anchor="start" x="233.5" y="-663.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="271.5" y="-663.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="281.5" y="-663.1" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="316.5" y="-663.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="183,-657 183,-732 370,-732 370,-657 183,-657"/>
</g>
<!-- note_models_transactions_SpecialTransaction&#45;&gt;note_models_transactions_Transaction -->
<g id="edge16" class="edge">
<title>note_models_transactions_SpecialTransaction&#45;&gt;note_models_transactions_Transaction</title>
<path fill="none" stroke="black" d="M280.8,-652.85C282.89,-633.07 285.51,-608.27 288.13,-583.55"/>
<polygon fill="none" stroke="black" points="291.63,-583.66 289.21,-573.35 284.67,-582.92 291.63,-583.66"/>
<text text-anchor="middle" x="307.5" y="-602.6" font-family="Roboto" font-size="8.00"> multi&#45;table</text>
<text text-anchor="middle" x="307.5" y="-593.6" font-family="Roboto" font-size="8.00">inheritance</text>
</g>
<!-- note_models_transactions_MembershipTransaction -->
<g id="node12" class="node">
<title>note_models_transactions_MembershipTransaction</title>
<polygon fill="white" stroke="transparent" points="404,-670 404,-719 591,-719 591,-670 404,-670"/>
<polygon fill="#1b563f" stroke="transparent" points="405.5,-696.5 405.5,-717.5 590.5,-717.5 590.5,-696.5 405.5,-696.5"/>
<text text-anchor="start" x="425" y="-705.5" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="435" y="-705.5" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;MembershipTransaction &#160;&#160;&#160;</text>
<text text-anchor="start" x="407.5" y="-689.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="417.5" y="-689.1" font-family="Roboto" font-weight="bold" font-size="8.00">transaction_ptr</text>
<text text-anchor="start" x="478.5" y="-689.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="492.5" y="-689.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="502.5" y="-689.1" font-family="Roboto" font-weight="bold" font-size="8.00">OneToOneField (id)</text>
<text text-anchor="start" x="578.5" y="-689.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="407.5" y="-676.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="417.5" y="-676.1" font-family="Roboto" font-weight="bold" font-size="8.00">membership</text>
<text text-anchor="start" x="466.5" y="-676.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="492.5" y="-676.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="502.5" y="-676.1" font-family="Roboto" font-weight="bold" font-size="8.00">OneToOneField (id)</text>
<text text-anchor="start" x="578.5" y="-676.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="404,-670 404,-719 591,-719 591,-670 404,-670"/>
</g>
<!-- note_models_transactions_MembershipTransaction&#45;&gt;note_models_transactions_Transaction -->
<g id="edge18" class="edge">
<title>note_models_transactions_MembershipTransaction&#45;&gt;note_models_transactions_Transaction</title>
<path fill="none" stroke="black" d="M472.42,-665.95C452.58,-644.15 423.52,-612.24 394.88,-580.77"/>
<polygon fill="none" stroke="black" points="397.32,-578.25 388,-573.21 392.14,-582.97 397.32,-578.25"/>
<text text-anchor="middle" x="436.5" y="-602.6" font-family="Roboto" font-size="8.00"> multi&#45;table</text>
<text text-anchor="middle" x="436.5" y="-593.6" font-family="Roboto" font-size="8.00">inheritance</text>
</g>
<!-- member_models_Membership -->
<g id="node16" class="node">
<title>member_models_Membership</title>
<polygon fill="white" stroke="transparent" points="431.5,-464.5 431.5,-485.5 517.5,-485.5 517.5,-464.5 431.5,-464.5"/>
<polygon fill="#1b563f" stroke="transparent" points="431.5,-464 431.5,-485 517.5,-485 517.5,-464 431.5,-464"/>
<text text-anchor="start" x="436" y="-472.4" font-family="Roboto" font-size="8.00"> &#160;</text>
<text text-anchor="start" x="441" y="-472.4" font-family="Roboto" font-size="12.00" fill="white">Membership</text>
<text text-anchor="start" x="508" y="-472.4" font-family="Roboto" font-size="8.00"> &#160;</text>
</g>
<!-- note_models_transactions_MembershipTransaction&#45;&gt;member_models_Membership -->
<g id="edge17" class="edge">
<title>note_models_transactions_MembershipTransaction&#45;&gt;member_models_Membership</title>
<path fill="none" stroke="black" d="M494.59,-665.95C489.76,-620.34 480.26,-530.46 476.3,-493.01"/>
<text text-anchor="middle" x="535.5" y="-598.1" font-family="Roboto" font-size="8.00"> membership (transaction)</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 55 KiB

171
docs/_static/img/graphs/permission.svg vendored Normal file
View File

@ -0,0 +1,171 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.44.1 (0)
-->
<!-- Title: model_graph Pages: 1 -->
<svg width="352pt" height="373pt"
viewBox="0.00 0.00 352.00 373.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 369)">
<title>model_graph</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-369 348,-369 348,4 -4,4"/>
<!-- permission_models_PermissionMask -->
<g id="node1" class="node">
<title>permission_models_PermissionMask</title>
<polygon fill="white" stroke="transparent" points="8,-4 8,-66 186,-66 186,-4 8,-4"/>
<polygon fill="#1b563f" stroke="transparent" points="9,-44 9,-65 185,-65 185,-44 9,-44"/>
<text text-anchor="start" x="41" y="-53" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="51" y="-53" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;PermissionMask &#160;&#160;&#160;</text>
<text text-anchor="start" x="11" y="-36.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21" y="-36.6" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="29" y="-36.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="74" y="-36.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="84" y="-36.6" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="122" y="-36.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11" y="-23.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21" y="-23.6" font-family="Roboto" font-size="8.00">description</text>
<text text-anchor="start" x="60" y="-23.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="74" y="-23.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="84" y="-23.6" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="119" y="-23.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11" y="-10.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21" y="-10.6" font-family="Roboto" font-size="8.00">rank</text>
<text text-anchor="start" x="37" y="-10.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="74" y="-10.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="84" y="-10.6" font-family="Roboto" font-size="8.00">PositiveSmallIntegerField</text>
<text text-anchor="start" x="173" y="-10.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="8,-4 8,-66 186,-66 186,-4 8,-4"/>
</g>
<!-- permission_models_Permission -->
<g id="node2" class="node">
<title>permission_models_Permission</title>
<polygon fill="white" stroke="transparent" points="104.5,-119 104.5,-246 255.5,-246 255.5,-119 104.5,-119"/>
<polygon fill="#1b563f" stroke="transparent" points="106,-223.5 106,-244.5 255,-244.5 255,-223.5 106,-223.5"/>
<text text-anchor="start" x="136.5" y="-232.5" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="146.5" y="-232.5" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;Permission &#160;&#160;&#160;</text>
<text text-anchor="start" x="108" y="-216.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="118" y="-216.1" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="126" y="-216.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="172" y="-216.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="182" y="-216.1" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="220" y="-216.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="108" y="-203.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="118" y="-203.1" font-family="Roboto" font-weight="bold" font-size="8.00">mask</text>
<text text-anchor="start" x="139" y="-203.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="172" y="-203.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="182" y="-203.1" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="243" y="-203.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="108" y="-190.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="118" y="-190.1" font-family="Roboto" font-weight="bold" font-size="8.00">model</text>
<text text-anchor="start" x="143" y="-190.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="172" y="-190.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="182" y="-190.1" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="243" y="-190.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="108" y="-177.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="118" y="-177.1" font-family="Roboto" font-size="8.00" fill="#7b7b7b">description</text>
<text text-anchor="start" x="157" y="-177.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="172" y="-177.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="182" y="-177.1" font-family="Roboto" font-size="8.00" fill="#7b7b7b">CharField</text>
<text text-anchor="start" x="217" y="-177.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="108" y="-164.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="118" y="-164.1" font-family="Roboto" font-size="8.00" fill="#7b7b7b">field</text>
<text text-anchor="start" x="133" y="-164.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="172" y="-164.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="182" y="-164.1" font-family="Roboto" font-size="8.00" fill="#7b7b7b">CharField</text>
<text text-anchor="start" x="217" y="-164.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="108" y="-151.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="118" y="-151.1" font-family="Roboto" font-size="8.00">permanent</text>
<text text-anchor="start" x="158" y="-151.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="172" y="-151.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="182" y="-151.1" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="228" y="-151.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="108" y="-138.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="118" y="-138.1" font-family="Roboto" font-size="8.00">query</text>
<text text-anchor="start" x="139" y="-138.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="172" y="-138.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="182" y="-138.1" font-family="Roboto" font-size="8.00">TextField</text>
<text text-anchor="start" x="214" y="-138.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="108" y="-125.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="118" y="-125.1" font-family="Roboto" font-size="8.00">type</text>
<text text-anchor="start" x="134" y="-125.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="172" y="-125.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="182" y="-125.1" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="217" y="-125.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="104.5,-119 104.5,-246 255.5,-246 255.5,-119 104.5,-119"/>
</g>
<!-- permission_models_Permission&#45;&gt;permission_models_PermissionMask -->
<g id="edge2" class="edge">
<title>permission_models_Permission&#45;&gt;permission_models_PermissionMask</title>
<path fill="none" stroke="black" d="M137.78,-107.48C130.35,-94.46 122.95,-81.49 116.54,-70.25"/>
<ellipse fill="black" stroke="black" cx="139.92" cy="-111.24" rx="4" ry="4"/>
<text text-anchor="middle" x="168" y="-90.6" font-family="Roboto" font-size="8.00"> mask (permissions)</text>
</g>
<!-- django_contrib_contenttypes_models_ContentType -->
<g id="node4" class="node">
<title>django_contrib_contenttypes_models_ContentType</title>
<polygon fill="white" stroke="transparent" points="220,-24.5 220,-45.5 306,-45.5 306,-24.5 220,-24.5"/>
<polygon fill="#1b563f" stroke="transparent" points="220,-24 220,-45 306,-45 306,-24 220,-24"/>
<text text-anchor="start" x="224" y="-32.4" font-family="Roboto" font-size="8.00"> &#160;</text>
<text text-anchor="start" x="229" y="-32.4" font-family="Roboto" font-size="12.00" fill="white">ContentType</text>
<text text-anchor="start" x="297" y="-32.4" font-family="Roboto" font-size="8.00"> &#160;</text>
</g>
<!-- permission_models_Permission&#45;&gt;django_contrib_contenttypes_models_ContentType -->
<g id="edge1" class="edge">
<title>permission_models_Permission&#45;&gt;django_contrib_contenttypes_models_ContentType</title>
<path fill="none" stroke="black" d="M222.21,-107.51C233.83,-87.14 245.38,-66.89 253.2,-53.17"/>
<ellipse fill="black" stroke="black" cx="220.08" cy="-111.24" rx="4" ry="4"/>
<text text-anchor="middle" x="249.5" y="-90.6" font-family="Roboto" font-size="8.00"> model (+)</text>
</g>
<!-- permission_models_Role -->
<g id="node3" class="node">
<title>permission_models_Role</title>
<polygon fill="white" stroke="transparent" points="173,-299 173,-361 317,-361 317,-299 173,-299"/>
<polygon fill="#1b563f" stroke="transparent" points="174,-339 174,-360 316,-360 316,-339 174,-339"/>
<text text-anchor="start" x="217" y="-348" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="227" y="-348" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;Role &#160;&#160;&#160;</text>
<text text-anchor="start" x="176" y="-331.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="186" y="-331.6" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="194" y="-331.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="233" y="-331.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="243" y="-331.6" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="281" y="-331.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="176" y="-318.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="186" y="-318.6" font-family="Roboto" font-weight="bold" font-size="8.00">for_club</text>
<text text-anchor="start" x="219" y="-318.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="233" y="-318.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="243" y="-318.6" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="304" y="-318.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="176" y="-305.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="186" y="-305.6" font-family="Roboto" font-size="8.00">name</text>
<text text-anchor="start" x="207" y="-305.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="233" y="-305.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="243" y="-305.6" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="278" y="-305.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="173,-299 173,-361 317,-361 317,-299 173,-299"/>
</g>
<!-- permission_models_Role&#45;&gt;permission_models_Permission -->
<g id="edge4" class="edge">
<title>permission_models_Role&#45;&gt;permission_models_Permission</title>
<path fill="none" stroke="black" d="M226.45,-287.47C222.27,-278.13 217.73,-267.95 213.16,-257.73"/>
<ellipse fill="black" stroke="black" cx="228.13" cy="-291.23" rx="4" ry="4"/>
<ellipse fill="black" stroke="black" cx="211.47" cy="-253.94" rx="4" ry="4"/>
<text text-anchor="middle" x="254" y="-270.6" font-family="Roboto" font-size="8.00"> permissions (role)</text>
</g>
<!-- member_models_Club -->
<g id="node5" class="node">
<title>member_models_Club</title>
<polygon fill="white" stroke="transparent" points="289,-172 289,-193 333,-193 333,-172 289,-172"/>
<polygon fill="#1b563f" stroke="transparent" points="289,-171.5 289,-192.5 333,-192.5 333,-171.5 289,-171.5"/>
<text text-anchor="start" x="293" y="-179.9" font-family="Roboto" font-size="8.00"> &#160;</text>
<text text-anchor="start" x="298" y="-179.9" font-family="Roboto" font-size="12.00" fill="white">Club</text>
<text text-anchor="start" x="324" y="-179.9" font-family="Roboto" font-size="8.00"> &#160;</text>
</g>
<!-- permission_models_Role&#45;&gt;member_models_Club -->
<g id="edge3" class="edge">
<title>permission_models_Role&#45;&gt;member_models_Club</title>
<path fill="none" stroke="black" d="M282.52,-288.02C284.92,-284.43 287.12,-280.73 289,-277 301.53,-252.13 307.07,-219.92 309.41,-200.53"/>
<ellipse fill="black" stroke="black" cx="280.03" cy="-291.53" rx="4" ry="4"/>
<text text-anchor="middle" x="318" y="-270.6" font-family="Roboto" font-size="8.00"> for_club (role)</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

324
docs/_static/img/graphs/treasury.svg vendored Normal file
View File

@ -0,0 +1,324 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.44.1 (0)
-->
<!-- Title: model_graph Pages: 1 -->
<svg width="970pt" height="493pt"
viewBox="0.00 0.00 970.00 493.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 489)">
<title>model_graph</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-489 966,-489 966,4 -4,4"/>
<!-- treasury_models_Invoice -->
<g id="node1" class="node">
<title>treasury_models_Invoice</title>
<polygon fill="white" stroke="transparent" points="8,-187 8,-340 176,-340 176,-187 8,-187"/>
<polygon fill="#1b563f" stroke="transparent" points="9,-317.5 9,-338.5 175,-338.5 175,-317.5 9,-317.5"/>
<text text-anchor="start" x="57.5" y="-326.5" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="67.5" y="-326.5" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;Invoice &#160;&#160;&#160;</text>
<text text-anchor="start" x="11" y="-310.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21" y="-310.1" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="29" y="-310.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="74" y="-310.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="84" y="-310.1" font-family="Roboto" font-weight="bold" font-size="8.00">PositiveIntegerField</text>
<text text-anchor="start" x="163" y="-310.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11" y="-297.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21" y="-297.1" font-family="Roboto" font-size="8.00">acquitted</text>
<text text-anchor="start" x="54" y="-297.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="74" y="-297.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="84" y="-297.1" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="130" y="-297.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11" y="-284.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21" y="-284.1" font-family="Roboto" font-size="8.00">address</text>
<text text-anchor="start" x="49" y="-284.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="74" y="-284.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="84" y="-284.1" font-family="Roboto" font-size="8.00">TextField</text>
<text text-anchor="start" x="116" y="-284.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11" y="-271.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21" y="-271.1" font-family="Roboto" font-size="8.00">bde</text>
<text text-anchor="start" x="35" y="-271.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="74" y="-271.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="84" y="-271.1" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="119" y="-271.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11" y="-258.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21" y="-258.1" font-family="Roboto" font-size="8.00">date</text>
<text text-anchor="start" x="37" y="-258.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="74" y="-258.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="84" y="-258.1" font-family="Roboto" font-size="8.00">DateField</text>
<text text-anchor="start" x="118" y="-258.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11" y="-245.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21" y="-245.1" font-family="Roboto" font-size="8.00">description</text>
<text text-anchor="start" x="60" y="-245.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="74" y="-245.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="84" y="-245.1" font-family="Roboto" font-size="8.00">TextField</text>
<text text-anchor="start" x="116" y="-245.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11" y="-232.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21" y="-232.1" font-family="Roboto" font-size="8.00">locked</text>
<text text-anchor="start" x="44" y="-232.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="74" y="-232.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="84" y="-232.1" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="130" y="-232.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11" y="-219.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21" y="-219.1" font-family="Roboto" font-size="8.00">name</text>
<text text-anchor="start" x="42" y="-219.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="74" y="-219.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="84" y="-219.1" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="119" y="-219.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11" y="-206.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21" y="-206.1" font-family="Roboto" font-size="8.00">object</text>
<text text-anchor="start" x="43" y="-206.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="74" y="-206.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="84" y="-206.1" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="119" y="-206.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="11" y="-193.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="21" y="-193.1" font-family="Roboto" font-size="8.00">tex</text>
<text text-anchor="start" x="32" y="-193.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="74" y="-193.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="84" y="-193.1" font-family="Roboto" font-size="8.00">TextField</text>
<text text-anchor="start" x="116" y="-193.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="8,-187 8,-340 176,-340 176,-187 8,-187"/>
</g>
<!-- treasury_models_Product -->
<g id="node2" class="node">
<title>treasury_models_Product</title>
<polygon fill="white" stroke="transparent" points="11.5,-393 11.5,-481 172.5,-481 172.5,-393 11.5,-393"/>
<polygon fill="#1b563f" stroke="transparent" points="13,-459 13,-480 172,-480 172,-459 13,-459"/>
<text text-anchor="start" x="57" y="-468" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="67" y="-468" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;Product &#160;&#160;&#160;</text>
<text text-anchor="start" x="15" y="-451.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="25" y="-451.6" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="33" y="-451.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="80" y="-451.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="90" y="-451.6" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="128" y="-451.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="15" y="-438.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="25" y="-438.6" font-family="Roboto" font-weight="bold" font-size="8.00">invoice</text>
<text text-anchor="start" x="53" y="-438.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="80" y="-438.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="90" y="-438.6" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="151" y="-438.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="15" y="-425.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="25" y="-425.6" font-family="Roboto" font-size="8.00">amount</text>
<text text-anchor="start" x="53" y="-425.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="80" y="-425.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="90" y="-425.6" font-family="Roboto" font-size="8.00">IntegerField</text>
<text text-anchor="start" x="133" y="-425.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="15" y="-412.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="25" y="-412.6" font-family="Roboto" font-size="8.00">designation</text>
<text text-anchor="start" x="66" y="-412.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="80" y="-412.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="90" y="-412.6" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="125" y="-412.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="15" y="-399.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="25" y="-399.6" font-family="Roboto" font-size="8.00">quantity</text>
<text text-anchor="start" x="53" y="-399.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="80" y="-399.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="90" y="-399.6" font-family="Roboto" font-size="8.00">PositiveIntegerField</text>
<text text-anchor="start" x="160" y="-399.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="11.5,-393 11.5,-481 172.5,-481 172.5,-393 11.5,-393"/>
</g>
<!-- treasury_models_Product&#45;&gt;treasury_models_Invoice -->
<g id="edge1" class="edge">
<title>treasury_models_Product&#45;&gt;treasury_models_Invoice</title>
<path fill="none" stroke="black" d="M92,-380.43C92,-368.88 92,-356.48 92,-344.25"/>
<ellipse fill="black" stroke="black" cx="92" cy="-384.68" rx="4" ry="4"/>
<text text-anchor="middle" x="124.5" y="-364.6" font-family="Roboto" font-size="8.00"> invoice (products)</text>
</g>
<!-- treasury_models_RemittanceType -->
<g id="node3" class="node">
<title>treasury_models_RemittanceType</title>
<polygon fill="white" stroke="transparent" points="213.5,-85 213.5,-134 382.5,-134 382.5,-85 213.5,-85"/>
<polygon fill="#1b563f" stroke="transparent" points="215,-111.5 215,-132.5 382,-132.5 382,-111.5 215,-111.5"/>
<text text-anchor="start" x="243" y="-120.5" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="253" y="-120.5" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;RemittanceType &#160;&#160;&#160;</text>
<text text-anchor="start" x="217" y="-104.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="227" y="-104.1" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="235" y="-104.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="259" y="-104.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="269" y="-104.1" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="307" y="-104.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="217" y="-91.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="227" y="-91.1" font-family="Roboto" font-weight="bold" font-size="8.00">note</text>
<text text-anchor="start" x="245" y="-91.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="259" y="-91.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="269" y="-91.1" font-family="Roboto" font-weight="bold" font-size="8.00">OneToOneField (note_ptr)</text>
<text text-anchor="start" x="370" y="-91.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="213.5,-85 213.5,-134 382.5,-134 382.5,-85 213.5,-85"/>
</g>
<!-- note_models_notes_NoteSpecial -->
<g id="node7" class="node">
<title>note_models_notes_NoteSpecial</title>
<polygon fill="white" stroke="transparent" points="255,-7.5 255,-28.5 341,-28.5 341,-7.5 255,-7.5"/>
<polygon fill="#1b563f" stroke="transparent" points="255,-7 255,-28 341,-28 341,-7 255,-7"/>
<text text-anchor="start" x="259.5" y="-15.4" font-family="Roboto" font-size="8.00"> &#160;</text>
<text text-anchor="start" x="264.5" y="-15.4" font-family="Roboto" font-size="12.00" fill="white">NoteSpecial</text>
<text text-anchor="start" x="331.5" y="-15.4" font-family="Roboto" font-size="8.00"> &#160;</text>
</g>
<!-- treasury_models_RemittanceType&#45;&gt;note_models_notes_NoteSpecial -->
<g id="edge2" class="edge">
<title>treasury_models_RemittanceType&#45;&gt;note_models_notes_NoteSpecial</title>
<path fill="none" stroke="black" d="M298,-80.67C298,-66.1 298,-48.72 298,-36.13"/>
<text text-anchor="middle" x="337.5" y="-56.6" font-family="Roboto" font-size="8.00"> note (remittancetype)</text>
</g>
<!-- treasury_models_Remittance -->
<g id="node4" class="node">
<title>treasury_models_Remittance</title>
<polygon fill="white" stroke="transparent" points="210.5,-219.5 210.5,-307.5 385.5,-307.5 385.5,-219.5 210.5,-219.5"/>
<polygon fill="#1b563f" stroke="transparent" points="212,-285.5 212,-306.5 385,-306.5 385,-285.5 212,-285.5"/>
<text text-anchor="start" x="254" y="-294.5" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="264" y="-294.5" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;Remittance &#160;&#160;&#160;</text>
<text text-anchor="start" x="214" y="-278.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="224" y="-278.1" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="232" y="-278.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="302" y="-278.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="312" y="-278.1" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="350" y="-278.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="214" y="-265.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="224" y="-265.1" font-family="Roboto" font-weight="bold" font-size="8.00">remittance_type</text>
<text text-anchor="start" x="288" y="-265.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="302" y="-265.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="312" y="-265.1" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="373" y="-265.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="214" y="-252.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="224" y="-252.1" font-family="Roboto" font-size="8.00">closed</text>
<text text-anchor="start" x="247" y="-252.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="302" y="-252.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="312" y="-252.1" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="358" y="-252.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="214" y="-239.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="224" y="-239.1" font-family="Roboto" font-size="8.00">comment</text>
<text text-anchor="start" x="258" y="-239.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="302" y="-239.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="312" y="-239.1" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="347" y="-239.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="214" y="-226.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="224" y="-226.1" font-family="Roboto" font-size="8.00">date</text>
<text text-anchor="start" x="240" y="-226.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="302" y="-226.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="312" y="-226.1" font-family="Roboto" font-size="8.00">DateTimeField</text>
<text text-anchor="start" x="364" y="-226.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="210.5,-219.5 210.5,-307.5 385.5,-307.5 385.5,-219.5 210.5,-219.5"/>
</g>
<!-- treasury_models_Remittance&#45;&gt;treasury_models_RemittanceType -->
<g id="edge3" class="edge">
<title>treasury_models_Remittance&#45;&gt;treasury_models_RemittanceType</title>
<path fill="none" stroke="black" d="M298,-207.09C298,-183.68 298,-157.46 298,-138.24"/>
<ellipse fill="black" stroke="black" cx="298" cy="-211.24" rx="4" ry="4"/>
<text text-anchor="middle" x="350" y="-158.6" font-family="Roboto" font-size="8.00"> remittance_type (remittance)</text>
</g>
<!-- treasury_models_SpecialTransactionProxy -->
<g id="node5" class="node">
<title>treasury_models_SpecialTransactionProxy</title>
<polygon fill="white" stroke="transparent" points="272.5,-406 272.5,-468 497.5,-468 497.5,-406 272.5,-406"/>
<polygon fill="#1b563f" stroke="transparent" points="274,-446 274,-467 497,-467 497,-446 274,-446"/>
<text text-anchor="start" x="310" y="-455" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="320" y="-455" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;SpecialTransactionProxy &#160;&#160;&#160;</text>
<text text-anchor="start" x="276" y="-438.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="286" y="-438.6" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="294" y="-438.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="346" y="-438.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="356" y="-438.6" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="394" y="-438.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="276" y="-425.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="286" y="-425.6" font-family="Roboto" font-weight="bold" font-size="8.00">remittance</text>
<text text-anchor="start" x="328" y="-425.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="346" y="-425.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="356" y="-425.6" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="417" y="-425.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="276" y="-412.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="286" y="-412.6" font-family="Roboto" font-weight="bold" font-size="8.00">transaction</text>
<text text-anchor="start" x="332" y="-412.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="346" y="-412.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="356" y="-412.6" font-family="Roboto" font-weight="bold" font-size="8.00">OneToOneField (transaction_ptr)</text>
<text text-anchor="start" x="485" y="-412.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="272.5,-406 272.5,-468 497.5,-468 497.5,-406 272.5,-406"/>
</g>
<!-- treasury_models_SpecialTransactionProxy&#45;&gt;treasury_models_Remittance -->
<g id="edge5" class="edge">
<title>treasury_models_SpecialTransactionProxy&#45;&gt;treasury_models_Remittance</title>
<path fill="none" stroke="black" d="M318.41,-396.34C310.62,-388.91 303.76,-380.46 299,-371 289.94,-353 288.41,-331.02 289.64,-311.71"/>
<ellipse fill="black" stroke="black" cx="321.56" cy="-399.15" rx="4" ry="4"/>
<text text-anchor="middle" x="364" y="-364.6" font-family="Roboto" font-size="8.00"> remittance (specialtransactionproxy)</text>
</g>
<!-- note_models_transactions_SpecialTransaction -->
<g id="node8" class="node">
<title>note_models_transactions_SpecialTransaction</title>
<polygon fill="white" stroke="transparent" points="483,-253 483,-274 605,-274 605,-253 483,-253"/>
<polygon fill="#1b563f" stroke="transparent" points="483,-252.5 483,-273.5 605,-273.5 605,-252.5 483,-252.5"/>
<text text-anchor="start" x="487.5" y="-260.9" font-family="Roboto" font-size="8.00"> &#160;</text>
<text text-anchor="start" x="492.5" y="-260.9" font-family="Roboto" font-size="12.00" fill="white">SpecialTransaction</text>
<text text-anchor="start" x="595.5" y="-260.9" font-family="Roboto" font-size="8.00"> &#160;</text>
</g>
<!-- treasury_models_SpecialTransactionProxy&#45;&gt;note_models_transactions_SpecialTransaction -->
<g id="edge4" class="edge">
<title>treasury_models_SpecialTransactionProxy&#45;&gt;note_models_transactions_SpecialTransaction</title>
<path fill="none" stroke="black" d="M415.54,-401.97C426.93,-389.37 440,-374.98 452,-362 478.22,-333.63 509.12,-301.06 527.61,-281.66"/>
<text text-anchor="middle" x="518" y="-364.6" font-family="Roboto" font-size="8.00"> transaction (specialtransactionproxy)</text>
</g>
<!-- treasury_models_SogeCredit -->
<g id="node6" class="node">
<title>treasury_models_SogeCredit</title>
<polygon fill="white" stroke="transparent" points="612,-406 612,-468 864,-468 864,-406 612,-406"/>
<polygon fill="#1b563f" stroke="transparent" points="613,-446 613,-467 863,-467 863,-446 613,-446"/>
<text text-anchor="start" x="694.5" y="-455" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="704.5" y="-455" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;SogeCredit &#160;&#160;&#160;</text>
<text text-anchor="start" x="615" y="-438.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="625" y="-438.6" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="633" y="-438.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="712" y="-438.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="722" y="-438.6" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="760" y="-438.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="615" y="-425.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="625" y="-425.6" font-family="Roboto" font-weight="bold" font-size="8.00">credit_transaction</text>
<text text-anchor="start" x="698" y="-425.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="712" y="-425.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="722" y="-425.6" font-family="Roboto" font-weight="bold" font-size="8.00">OneToOneField (transaction_ptr)</text>
<text text-anchor="start" x="851" y="-425.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="615" y="-412.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="625" y="-412.6" font-family="Roboto" font-weight="bold" font-size="8.00">user</text>
<text text-anchor="start" x="643" y="-412.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="712" y="-412.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="722" y="-412.6" font-family="Roboto" font-weight="bold" font-size="8.00">OneToOneField (id)</text>
<text text-anchor="start" x="798" y="-412.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="612,-406 612,-468 864,-468 864,-406 612,-406"/>
</g>
<!-- treasury_models_SogeCredit&#45;&gt;note_models_transactions_SpecialTransaction -->
<g id="edge7" class="edge">
<title>treasury_models_SogeCredit&#45;&gt;note_models_transactions_SpecialTransaction</title>
<path fill="none" stroke="black" d="M668.71,-401.98C653.52,-392.97 638.09,-382.51 625,-371 594.47,-344.16 567.83,-304.24 554.03,-281.68"/>
<text text-anchor="middle" x="679.5" y="-364.6" font-family="Roboto" font-size="8.00"> credit_transaction (sogecredit)</text>
</g>
<!-- django_contrib_auth_models_User -->
<g id="node9" class="node">
<title>django_contrib_auth_models_User</title>
<polygon fill="white" stroke="transparent" points="716,-253 716,-274 760,-274 760,-253 716,-253"/>
<polygon fill="#1b563f" stroke="transparent" points="716,-252.5 716,-273.5 760,-273.5 760,-252.5 716,-252.5"/>
<text text-anchor="start" x="720" y="-260.9" font-family="Roboto" font-size="8.00"> &#160;</text>
<text text-anchor="start" x="725" y="-260.9" font-family="Roboto" font-size="12.00" fill="white">User</text>
<text text-anchor="start" x="751" y="-260.9" font-family="Roboto" font-size="8.00"> &#160;</text>
</g>
<!-- treasury_models_SogeCredit&#45;&gt;django_contrib_auth_models_User -->
<g id="edge6" class="edge">
<title>treasury_models_SogeCredit&#45;&gt;django_contrib_auth_models_User</title>
<path fill="none" stroke="black" d="M738,-401.71C738,-365.34 738,-309.39 738,-281.51"/>
<text text-anchor="middle" x="769.5" y="-364.6" font-family="Roboto" font-size="8.00"> user (sogecredit)</text>
</g>
<!-- note_models_transactions_MembershipTransaction -->
<g id="node10" class="node">
<title>note_models_transactions_MembershipTransaction</title>
<polygon fill="white" stroke="transparent" points="794,-253 794,-274 940,-274 940,-253 794,-253"/>
<polygon fill="#1b563f" stroke="transparent" points="794,-252.5 794,-273.5 940,-273.5 940,-252.5 794,-252.5"/>
<text text-anchor="start" x="798" y="-260.9" font-family="Roboto" font-size="8.00"> &#160;</text>
<text text-anchor="start" x="803" y="-260.9" font-family="Roboto" font-size="12.00" fill="white">MembershipTransaction</text>
<text text-anchor="start" x="931" y="-260.9" font-family="Roboto" font-size="8.00"> &#160;</text>
</g>
<!-- treasury_models_SogeCredit&#45;&gt;note_models_transactions_MembershipTransaction -->
<g id="edge8" class="edge">
<title>treasury_models_SogeCredit&#45;&gt;note_models_transactions_MembershipTransaction</title>
<path fill="none" stroke="black" d="M782.72,-395.99C790.55,-388.06 798.32,-379.54 805,-371 825.4,-344.92 843.79,-311.46 855.15,-289.06"/>
<ellipse fill="black" stroke="black" cx="779.57" cy="-399.11" rx="4" ry="4"/>
<ellipse fill="black" stroke="black" cx="857.08" cy="-285.21" rx="4" ry="4"/>
<text text-anchor="middle" x="886.5" y="-364.6" font-family="Roboto" font-size="8.00"> transactions (_sogecredit_transactions_+)</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 29 KiB

603
docs/_static/img/graphs/wei.svg vendored Normal file
View File

@ -0,0 +1,603 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.44.1 (0)
-->
<!-- Title: model_graph Pages: 1 -->
<svg width="1207pt" height="864pt"
viewBox="0.00 0.00 1206.76 864.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 860)">
<title>model_graph</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-860 1202.76,-860 1202.76,4 -4,4"/>
<!-- wei_models_WEIClub -->
<g id="node1" class="node">
<title>wei_models_WEIClub</title>
<polygon fill="white" stroke="transparent" points="357.76,-219 357.76,-294 520.76,-294 520.76,-219 357.76,-219"/>
<polygon fill="#1b563f" stroke="transparent" points="359.26,-271.5 359.26,-292.5 520.26,-292.5 520.26,-271.5 359.26,-271.5"/>
<text text-anchor="start" x="401.76" y="-280.5" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="411.76" y="-280.5" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;WEIClub &#160;&#160;&#160;</text>
<text text-anchor="start" x="361.26" y="-264.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="371.26" y="-264.1" font-family="Roboto" font-weight="bold" font-size="8.00">club_ptr</text>
<text text-anchor="start" x="404.26" y="-264.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="422.26" y="-264.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="432.26" y="-264.1" font-family="Roboto" font-weight="bold" font-size="8.00">OneToOneField (id)</text>
<text text-anchor="start" x="508.26" y="-264.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="361.26" y="-251.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="371.26" y="-251.1" font-family="Roboto" font-size="8.00">date_end</text>
<text text-anchor="start" x="405.26" y="-251.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="422.26" y="-251.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="432.26" y="-251.1" font-family="Roboto" font-size="8.00">DateField</text>
<text text-anchor="start" x="466.26" y="-251.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="361.26" y="-238.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="371.26" y="-238.1" font-family="Roboto" font-size="8.00">date_start</text>
<text text-anchor="start" x="408.26" y="-238.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="422.26" y="-238.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="432.26" y="-238.1" font-family="Roboto" font-size="8.00">DateField</text>
<text text-anchor="start" x="466.26" y="-238.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="361.26" y="-225.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="371.26" y="-225.1" font-family="Roboto" font-size="8.00">year</text>
<text text-anchor="start" x="387.26" y="-225.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="422.26" y="-225.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="432.26" y="-225.1" font-family="Roboto" font-size="8.00">PositiveIntegerField</text>
<text text-anchor="start" x="502.26" y="-225.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="357.76,-219 357.76,-294 520.76,-294 520.76,-219 357.76,-219"/>
</g>
<!-- member_models_Club -->
<g id="node8" class="node">
<title>member_models_Club</title>
<polygon fill="white" stroke="transparent" points="554.76,-4 554.76,-157 763.76,-157 763.76,-4 554.76,-4"/>
<polygon fill="#1b563f" stroke="transparent" points="556.26,-134.5 556.26,-155.5 763.26,-155.5 763.26,-134.5 556.26,-134.5"/>
<text text-anchor="start" x="631.26" y="-143.5" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="641.26" y="-143.5" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;Club &#160;&#160;&#160;</text>
<text text-anchor="start" x="558.26" y="-127.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="568.26" y="-127.1" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="576.26" y="-127.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="671.26" y="-127.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="681.26" y="-127.1" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="719.26" y="-127.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="558.26" y="-114.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="568.26" y="-114.1" font-family="Roboto" font-weight="bold" font-size="8.00" fill="#7b7b7b">parent_club</text>
<text text-anchor="start" x="616.26" y="-114.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="671.26" y="-114.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="681.26" y="-114.1" font-family="Roboto" font-weight="bold" font-size="8.00" fill="#7b7b7b">ForeignKey (id)</text>
<text text-anchor="start" x="742.26" y="-114.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="558.26" y="-101.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="568.26" y="-101.1" font-family="Roboto" font-size="8.00">email</text>
<text text-anchor="start" x="587.26" y="-101.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="671.26" y="-101.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="681.26" y="-101.1" font-family="Roboto" font-size="8.00">EmailField</text>
<text text-anchor="start" x="718.26" y="-101.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="558.26" y="-88.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="568.26" y="-88.1" font-family="Roboto" font-size="8.00" fill="#7b7b7b">membership_duration</text>
<text text-anchor="start" x="647.26" y="-88.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="671.26" y="-88.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="681.26" y="-88.1" font-family="Roboto" font-size="8.00" fill="#7b7b7b">PositiveIntegerField</text>
<text text-anchor="start" x="751.26" y="-88.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="558.26" y="-75.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="568.26" y="-75.1" font-family="Roboto" font-size="8.00" fill="#7b7b7b">membership_end</text>
<text text-anchor="start" x="631.26" y="-75.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="671.26" y="-75.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="681.26" y="-75.1" font-family="Roboto" font-size="8.00" fill="#7b7b7b">DateField</text>
<text text-anchor="start" x="715.26" y="-75.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="558.26" y="-62.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="568.26" y="-62.1" font-family="Roboto" font-size="8.00">membership_fee_paid</text>
<text text-anchor="start" x="648.26" y="-62.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="671.26" y="-62.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="681.26" y="-62.1" font-family="Roboto" font-size="8.00">PositiveIntegerField</text>
<text text-anchor="start" x="751.26" y="-62.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="558.26" y="-49.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="568.26" y="-49.1" font-family="Roboto" font-size="8.00">membership_fee_unpaid</text>
<text text-anchor="start" x="657.26" y="-49.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="671.26" y="-49.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="681.26" y="-49.1" font-family="Roboto" font-size="8.00">PositiveIntegerField</text>
<text text-anchor="start" x="751.26" y="-49.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="558.26" y="-36.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="568.26" y="-36.1" font-family="Roboto" font-size="8.00" fill="#7b7b7b">membership_start</text>
<text text-anchor="start" x="633.26" y="-36.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="671.26" y="-36.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="681.26" y="-36.1" font-family="Roboto" font-size="8.00" fill="#7b7b7b">DateField</text>
<text text-anchor="start" x="715.26" y="-36.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="558.26" y="-23.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="568.26" y="-23.1" font-family="Roboto" font-size="8.00">name</text>
<text text-anchor="start" x="589.26" y="-23.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="671.26" y="-23.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="681.26" y="-23.1" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="716.26" y="-23.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="558.26" y="-10.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="568.26" y="-10.1" font-family="Roboto" font-size="8.00">require_memberships</text>
<text text-anchor="start" x="645.26" y="-10.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="671.26" y="-10.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="681.26" y="-10.1" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="727.26" y="-10.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="554.76,-4 554.76,-157 763.76,-157 763.76,-4 554.76,-4"/>
</g>
<!-- wei_models_WEIClub&#45;&gt;member_models_Club -->
<g id="edge1" class="edge">
<title>wei_models_WEIClub&#45;&gt;member_models_Club</title>
<path fill="none" stroke="black" d="M490.56,-214.92C508.57,-200.68 529.56,-184.08 550.48,-167.53"/>
<polygon fill="none" stroke="black" points="552.82,-170.14 558.49,-161.2 548.48,-164.65 552.82,-170.14"/>
<text text-anchor="middle" x="550.26" y="-190.6" font-family="Roboto" font-size="8.00"> multi&#45;table</text>
<text text-anchor="middle" x="550.26" y="-181.6" font-family="Roboto" font-size="8.00">inheritance</text>
</g>
<!-- wei_models_Bus -->
<g id="node2" class="node">
<title>wei_models_Bus</title>
<polygon fill="white" stroke="transparent" points="112.26,-347 112.26,-435 306.26,-435 306.26,-347 112.26,-347"/>
<polygon fill="#1b563f" stroke="transparent" points="113.26,-413 113.26,-434 305.26,-434 305.26,-413 113.26,-413"/>
<text text-anchor="start" x="182.76" y="-422" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="192.76" y="-422" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;Bus &#160;&#160;&#160;</text>
<text text-anchor="start" x="115.26" y="-405.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="125.26" y="-405.6" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="133.26" y="-405.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="198.26" y="-405.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="208.26" y="-405.6" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="246.26" y="-405.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="115.26" y="-392.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="125.26" y="-392.6" font-family="Roboto" font-weight="bold" font-size="8.00">wei</text>
<text text-anchor="start" x="138.26" y="-392.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="198.26" y="-392.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="208.26" y="-392.6" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (club_ptr)</text>
<text text-anchor="start" x="293.26" y="-392.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="115.26" y="-379.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="125.26" y="-379.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">description</text>
<text text-anchor="start" x="164.26" y="-379.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="198.26" y="-379.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="208.26" y="-379.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">TextField</text>
<text text-anchor="start" x="240.26" y="-379.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="115.26" y="-366.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="125.26" y="-366.6" font-family="Roboto" font-size="8.00">information_json</text>
<text text-anchor="start" x="184.26" y="-366.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="198.26" y="-366.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="208.26" y="-366.6" font-family="Roboto" font-size="8.00">TextField</text>
<text text-anchor="start" x="240.26" y="-366.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="115.26" y="-353.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="125.26" y="-353.6" font-family="Roboto" font-size="8.00">name</text>
<text text-anchor="start" x="146.26" y="-353.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="198.26" y="-353.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="208.26" y="-353.6" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="243.26" y="-353.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="112.26,-347 112.26,-435 306.26,-435 306.26,-347 112.26,-347"/>
</g>
<!-- wei_models_Bus&#45;&gt;wei_models_WEIClub -->
<g id="edge2" class="edge">
<title>wei_models_Bus&#45;&gt;wei_models_WEIClub</title>
<path fill="none" stroke="black" d="M298.21,-338.76C321.62,-325.27 346.55,-310.91 368.84,-298.07"/>
<ellipse fill="black" stroke="black" cx="294.46" cy="-340.92" rx="4" ry="4"/>
<text text-anchor="middle" x="353.26" y="-318.6" font-family="Roboto" font-size="8.00"> wei (buses)</text>
</g>
<!-- wei_models_BusTeam -->
<g id="node3" class="node">
<title>wei_models_BusTeam</title>
<polygon fill="white" stroke="transparent" points="129.76,-562 129.76,-650 288.76,-650 288.76,-562 129.76,-562"/>
<polygon fill="#1b563f" stroke="transparent" points="131.26,-628 131.26,-649 288.26,-649 288.26,-628 131.26,-628"/>
<text text-anchor="start" x="170.76" y="-637" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="180.76" y="-637" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;BusTeam &#160;&#160;&#160;</text>
<text text-anchor="start" x="133.26" y="-620.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="143.26" y="-620.6" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="151.26" y="-620.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="196.26" y="-620.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="206.26" y="-620.6" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="244.26" y="-620.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="133.26" y="-607.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="143.26" y="-607.6" font-family="Roboto" font-weight="bold" font-size="8.00">bus</text>
<text text-anchor="start" x="159.26" y="-607.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="196.26" y="-607.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="206.26" y="-607.6" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="267.26" y="-607.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="133.26" y="-594.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="143.26" y="-594.6" font-family="Roboto" font-size="8.00">color</text>
<text text-anchor="start" x="161.26" y="-594.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="196.26" y="-594.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="206.26" y="-594.6" font-family="Roboto" font-size="8.00">PositiveIntegerField</text>
<text text-anchor="start" x="276.26" y="-594.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="133.26" y="-581.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="143.26" y="-581.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">description</text>
<text text-anchor="start" x="182.26" y="-581.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="196.26" y="-581.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="206.26" y="-581.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">TextField</text>
<text text-anchor="start" x="238.26" y="-581.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="133.26" y="-568.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="143.26" y="-568.6" font-family="Roboto" font-size="8.00">name</text>
<text text-anchor="start" x="164.26" y="-568.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="196.26" y="-568.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="206.26" y="-568.6" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="241.26" y="-568.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="129.76,-562 129.76,-650 288.76,-650 288.76,-562 129.76,-562"/>
</g>
<!-- wei_models_BusTeam&#45;&gt;wei_models_Bus -->
<g id="edge3" class="edge">
<title>wei_models_BusTeam&#45;&gt;wei_models_Bus</title>
<path fill="none" stroke="black" d="M209.26,-549.93C209.26,-515.64 209.26,-471.98 209.26,-439.26"/>
<ellipse fill="black" stroke="black" cx="209.26" cy="-553.99" rx="4" ry="4"/>
<text text-anchor="middle" x="232.26" y="-464.1" font-family="Roboto" font-size="8.00"> bus (teams)</text>
</g>
<!-- wei_models_WEIRole -->
<g id="node4" class="node">
<title>wei_models_WEIRole</title>
<polygon fill="white" stroke="transparent" points="589.76,-588 589.76,-624 746.76,-624 746.76,-588 589.76,-588"/>
<polygon fill="#1b563f" stroke="transparent" points="591.26,-602 591.26,-623 746.26,-623 746.26,-602 591.26,-602"/>
<text text-anchor="start" x="631.26" y="-611" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="641.26" y="-611" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;WEIRole &#160;&#160;&#160;</text>
<text text-anchor="start" x="593.26" y="-594.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="603.26" y="-594.6" font-family="Roboto" font-weight="bold" font-size="8.00">role_ptr</text>
<text text-anchor="start" x="634.26" y="-594.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="648.26" y="-594.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="658.26" y="-594.6" font-family="Roboto" font-weight="bold" font-size="8.00">OneToOneField (id)</text>
<text text-anchor="start" x="734.26" y="-594.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="589.76,-588 589.76,-624 746.76,-624 746.76,-588 589.76,-588"/>
</g>
<!-- permission_models_Role -->
<g id="node10" class="node">
<title>permission_models_Role</title>
<polygon fill="white" stroke="transparent" points="667.26,-380.5 667.26,-401.5 711.26,-401.5 711.26,-380.5 667.26,-380.5"/>
<polygon fill="#1b563f" stroke="transparent" points="667.26,-380 667.26,-401 711.26,-401 711.26,-380 667.26,-380"/>
<text text-anchor="start" x="671.76" y="-388.4" font-family="Roboto" font-size="8.00"> &#160;</text>
<text text-anchor="start" x="676.76" y="-388.4" font-family="Roboto" font-size="12.00" fill="white">Role</text>
<text text-anchor="start" x="701.76" y="-388.4" font-family="Roboto" font-size="8.00"> &#160;</text>
</g>
<!-- wei_models_WEIRole&#45;&gt;permission_models_Role -->
<g id="edge4" class="edge">
<title>wei_models_WEIRole&#45;&gt;permission_models_Role</title>
<path fill="none" stroke="black" d="M663.01,-583.63C656.73,-554.58 648.26,-501.21 658.26,-457 661.3,-443.57 667.46,-429.66 673.5,-418.17"/>
<polygon fill="none" stroke="black" points="676.71,-419.6 678.47,-409.16 670.57,-416.23 676.71,-419.6"/>
<text text-anchor="middle" x="678.26" y="-468.6" font-family="Roboto" font-size="8.00"> multi&#45;table</text>
<text text-anchor="middle" x="678.26" y="-459.6" font-family="Roboto" font-size="8.00">inheritance</text>
</g>
<!-- wei_models_WEIRegistration -->
<g id="node5" class="node">
<title>wei_models_WEIRegistration</title>
<polygon fill="white" stroke="transparent" points="323.26,-503.5 323.26,-708.5 555.26,-708.5 555.26,-503.5 323.26,-503.5"/>
<polygon fill="#1b563f" stroke="transparent" points="324.26,-686 324.26,-707 554.26,-707 554.26,-686 324.26,-686"/>
<text text-anchor="start" x="384.26" y="-695" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="394.26" y="-695" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;WEIRegistration &#160;&#160;&#160;</text>
<text text-anchor="start" x="326.26" y="-678.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="336.26" y="-678.6" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="344.26" y="-678.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="447.26" y="-678.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="457.26" y="-678.6" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="495.26" y="-678.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="326.26" y="-665.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="336.26" y="-665.6" font-family="Roboto" font-weight="bold" font-size="8.00">user</text>
<text text-anchor="start" x="354.26" y="-665.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="447.26" y="-665.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="457.26" y="-665.6" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="518.26" y="-665.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="326.26" y="-652.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="336.26" y="-652.6" font-family="Roboto" font-weight="bold" font-size="8.00">wei</text>
<text text-anchor="start" x="349.26" y="-652.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="447.26" y="-652.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="457.26" y="-652.6" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (club_ptr)</text>
<text text-anchor="start" x="542.26" y="-652.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="326.26" y="-639.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="336.26" y="-639.6" font-family="Roboto" font-size="8.00">birth_date</text>
<text text-anchor="start" x="373.26" y="-639.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="447.26" y="-639.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="457.26" y="-639.6" font-family="Roboto" font-size="8.00">DateField</text>
<text text-anchor="start" x="491.26" y="-639.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="326.26" y="-626.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="336.26" y="-626.6" font-family="Roboto" font-size="8.00">caution_check</text>
<text text-anchor="start" x="387.26" y="-626.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="447.26" y="-626.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="457.26" y="-626.6" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="503.26" y="-626.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="326.26" y="-613.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="336.26" y="-613.6" font-family="Roboto" font-size="8.00">clothing_cut</text>
<text text-anchor="start" x="379.26" y="-613.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="447.26" y="-613.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="457.26" y="-613.6" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="492.26" y="-613.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="326.26" y="-600.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="336.26" y="-600.6" font-family="Roboto" font-size="8.00">clothing_size</text>
<text text-anchor="start" x="382.26" y="-600.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="447.26" y="-600.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="457.26" y="-600.6" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="492.26" y="-600.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="326.26" y="-587.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="336.26" y="-587.6" font-family="Roboto" font-size="8.00">emergency_contact_name</text>
<text text-anchor="start" x="431.26" y="-587.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="447.26" y="-587.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="457.26" y="-587.6" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="492.26" y="-587.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="326.26" y="-574.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="336.26" y="-574.6" font-family="Roboto" font-size="8.00">emergency_contact_phone</text>
<text text-anchor="start" x="433.26" y="-574.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="447.26" y="-574.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="457.26" y="-574.6" font-family="Roboto" font-size="8.00">PhoneNumberField</text>
<text text-anchor="start" x="527.26" y="-574.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="326.26" y="-561.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="336.26" y="-561.6" font-family="Roboto" font-size="8.00">first_year</text>
<text text-anchor="start" x="370.26" y="-561.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="447.26" y="-561.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="457.26" y="-561.6" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="503.26" y="-561.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="326.26" y="-548.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="336.26" y="-548.6" font-family="Roboto" font-size="8.00">gender</text>
<text text-anchor="start" x="362.26" y="-548.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="447.26" y="-548.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="457.26" y="-548.6" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="492.26" y="-548.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="326.26" y="-535.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="336.26" y="-535.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">health_issues</text>
<text text-anchor="start" x="385.26" y="-535.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="447.26" y="-535.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="457.26" y="-535.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">TextField</text>
<text text-anchor="start" x="489.26" y="-535.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="326.26" y="-522.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="336.26" y="-522.6" font-family="Roboto" font-size="8.00">information_json</text>
<text text-anchor="start" x="395.26" y="-522.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="447.26" y="-522.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="457.26" y="-522.6" font-family="Roboto" font-size="8.00">TextField</text>
<text text-anchor="start" x="489.26" y="-522.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="326.26" y="-509.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="336.26" y="-509.6" font-family="Roboto" font-size="8.00">soge_credit</text>
<text text-anchor="start" x="377.26" y="-509.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="447.26" y="-509.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="457.26" y="-509.6" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="503.26" y="-509.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="323.26,-503.5 323.26,-708.5 555.26,-708.5 555.26,-503.5 323.26,-503.5"/>
</g>
<!-- wei_models_WEIRegistration&#45;&gt;wei_models_WEIClub -->
<g id="edge6" class="edge">
<title>wei_models_WEIRegistration&#45;&gt;wei_models_WEIClub</title>
<path fill="none" stroke="black" d="M439.26,-491.29C439.26,-424.89 439.26,-345.15 439.26,-298.05"/>
<ellipse fill="black" stroke="black" cx="439.26" cy="-495.32" rx="4" ry="4"/>
<text text-anchor="middle" x="460.76" y="-389.1" font-family="Roboto" font-size="8.00"> wei (users)</text>
</g>
<!-- django_contrib_auth_models_User -->
<g id="node11" class="node">
<title>django_contrib_auth_models_User</title>
<polygon fill="white" stroke="transparent" points="905.26,-380.5 905.26,-401.5 949.26,-401.5 949.26,-380.5 905.26,-380.5"/>
<polygon fill="#1b563f" stroke="transparent" points="905.26,-380 905.26,-401 949.26,-401 949.26,-380 905.26,-380"/>
<text text-anchor="start" x="909.26" y="-388.4" font-family="Roboto" font-size="8.00"> &#160;</text>
<text text-anchor="start" x="914.26" y="-388.4" font-family="Roboto" font-size="12.00" fill="white">User</text>
<text text-anchor="start" x="940.26" y="-388.4" font-family="Roboto" font-size="8.00"> &#160;</text>
</g>
<!-- wei_models_WEIRegistration&#45;&gt;django_contrib_auth_models_User -->
<g id="edge5" class="edge">
<title>wei_models_WEIRegistration&#45;&gt;django_contrib_auth_models_User</title>
<path fill="none" stroke="black" d="M565.81,-495.81C567.95,-494.83 570.1,-493.89 572.26,-493 663.38,-455.48 699.65,-505.8 793.26,-475 837.19,-460.54 881.52,-429 906.57,-409.23"/>
<ellipse fill="black" stroke="black" cx="562.18" cy="-497.57" rx="4" ry="4"/>
<text text-anchor="middle" x="852.76" y="-464.1" font-family="Roboto" font-size="8.00"> user (wei)</text>
</g>
<!-- wei_models_WEIMembership -->
<g id="node6" class="node">
<title>wei_models_WEIMembership</title>
<polygon fill="white" stroke="transparent" points="196.26,-777 196.26,-852 386.26,-852 386.26,-777 196.26,-777"/>
<polygon fill="#1b563f" stroke="transparent" points="197.26,-829.5 197.26,-850.5 385.26,-850.5 385.26,-829.5 197.26,-829.5"/>
<text text-anchor="start" x="235.76" y="-838.5" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="245.76" y="-838.5" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;WEIMembership &#160;&#160;&#160;</text>
<text text-anchor="start" x="199.26" y="-822.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="209.26" y="-822.1" font-family="Roboto" font-weight="bold" font-size="8.00">membership_ptr</text>
<text text-anchor="start" x="273.26" y="-822.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="287.26" y="-822.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="297.26" y="-822.1" font-family="Roboto" font-weight="bold" font-size="8.00">OneToOneField (id)</text>
<text text-anchor="start" x="373.26" y="-822.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="199.26" y="-809.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="209.26" y="-809.1" font-family="Roboto" font-weight="bold" font-size="8.00">bus</text>
<text text-anchor="start" x="225.26" y="-809.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="287.26" y="-809.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="297.26" y="-809.1" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="358.26" y="-809.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="199.26" y="-796.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="209.26" y="-796.1" font-family="Roboto" font-weight="bold" font-size="8.00" fill="#7b7b7b">registration</text>
<text text-anchor="start" x="255.26" y="-796.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="287.26" y="-796.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="297.26" y="-796.1" font-family="Roboto" font-weight="bold" font-size="8.00" fill="#7b7b7b">OneToOneField (id)</text>
<text text-anchor="start" x="373.26" y="-796.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="199.26" y="-783.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="209.26" y="-783.1" font-family="Roboto" font-weight="bold" font-size="8.00" fill="#7b7b7b">team</text>
<text text-anchor="start" x="228.26" y="-783.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="287.26" y="-783.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="297.26" y="-783.1" font-family="Roboto" font-weight="bold" font-size="8.00" fill="#7b7b7b">ForeignKey (id)</text>
<text text-anchor="start" x="358.26" y="-783.1" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="196.26,-777 196.26,-852 386.26,-852 386.26,-777 196.26,-777"/>
</g>
<!-- wei_models_WEIMembership&#45;&gt;wei_models_Bus -->
<g id="edge7" class="edge">
<title>wei_models_WEIMembership&#45;&gt;wei_models_Bus</title>
<path fill="none" stroke="black" d="M180.12,-800.54C128.6,-788.33 71.89,-764.71 40.26,-719 -16.9,-636.4 -9.31,-580.36 40.26,-493 54.76,-467.43 78.6,-447.65 103.85,-432.64"/>
<ellipse fill="black" stroke="black" cx="184.11" cy="-801.44" rx="4" ry="4"/>
<text text-anchor="middle" x="76.26" y="-604.1" font-family="Roboto" font-size="8.00"> bus (memberships)</text>
</g>
<!-- wei_models_WEIMembership&#45;&gt;wei_models_BusTeam -->
<g id="edge8" class="edge">
<title>wei_models_WEIMembership&#45;&gt;wei_models_BusTeam</title>
<path fill="none" stroke="black" d="M271.95,-764.88C258.68,-731.47 241.16,-687.33 228.01,-654.22"/>
<ellipse fill="black" stroke="black" cx="273.58" cy="-768.98" rx="4" ry="4"/>
<text text-anchor="middle" x="305.76" y="-744.1" font-family="Roboto" font-size="8.00"> team (memberships)</text>
</g>
<!-- wei_models_WEIMembership&#45;&gt;wei_models_WEIRegistration -->
<g id="edge9" class="edge">
<title>wei_models_WEIMembership&#45;&gt;wei_models_WEIRegistration</title>
<path fill="none" stroke="black" d="M332.93,-772.99C338.3,-767.14 343.55,-761.04 348.26,-755 358.55,-741.79 368.65,-727.36 378.17,-712.85"/>
<text text-anchor="middle" x="407.26" y="-744.1" font-family="Roboto" font-size="8.00"> registration (membership)</text>
</g>
<!-- member_models_Membership -->
<g id="node9" class="node">
<title>member_models_Membership</title>
<polygon fill="white" stroke="transparent" points="780.76,-555.5 780.76,-656.5 937.76,-656.5 937.76,-555.5 780.76,-555.5"/>
<polygon fill="#1b563f" stroke="transparent" points="782.26,-634 782.26,-655 937.26,-655 937.26,-634 782.26,-634"/>
<text text-anchor="start" x="813.76" y="-643" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="823.76" y="-643" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;Membership &#160;&#160;&#160;</text>
<text text-anchor="start" x="784.26" y="-626.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="794.26" y="-626.6" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="802.26" y="-626.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="845.26" y="-626.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="855.26" y="-626.6" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="893.26" y="-626.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="784.26" y="-613.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="794.26" y="-613.6" font-family="Roboto" font-weight="bold" font-size="8.00">club</text>
<text text-anchor="start" x="812.26" y="-613.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="845.26" y="-613.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="855.26" y="-613.6" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="916.26" y="-613.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="784.26" y="-600.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="794.26" y="-600.6" font-family="Roboto" font-weight="bold" font-size="8.00">user</text>
<text text-anchor="start" x="812.26" y="-600.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="845.26" y="-600.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="855.26" y="-600.6" font-family="Roboto" font-weight="bold" font-size="8.00">ForeignKey (id)</text>
<text text-anchor="start" x="916.26" y="-600.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="784.26" y="-587.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="794.26" y="-587.6" font-family="Roboto" font-size="8.00">date_end</text>
<text text-anchor="start" x="828.26" y="-587.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="845.26" y="-587.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="855.26" y="-587.6" font-family="Roboto" font-size="8.00">DateField</text>
<text text-anchor="start" x="889.26" y="-587.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="784.26" y="-574.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="794.26" y="-574.6" font-family="Roboto" font-size="8.00">date_start</text>
<text text-anchor="start" x="831.26" y="-574.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="845.26" y="-574.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="855.26" y="-574.6" font-family="Roboto" font-size="8.00">DateField</text>
<text text-anchor="start" x="889.26" y="-574.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="784.26" y="-561.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="794.26" y="-561.6" font-family="Roboto" font-size="8.00">fee</text>
<text text-anchor="start" x="806.26" y="-561.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="845.26" y="-561.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="855.26" y="-561.6" font-family="Roboto" font-size="8.00">PositiveIntegerField</text>
<text text-anchor="start" x="925.26" y="-561.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="780.76,-555.5 780.76,-656.5 937.76,-656.5 937.76,-555.5 780.76,-555.5"/>
</g>
<!-- wei_models_WEIMembership&#45;&gt;member_models_Membership -->
<g id="edge10" class="edge">
<title>wei_models_WEIMembership&#45;&gt;member_models_Membership</title>
<path fill="none" stroke="black" d="M394.29,-811.98C494.78,-806.29 648.78,-786.06 763.26,-719 784.62,-706.48 803.55,-687.45 818.82,-668.6"/>
<polygon fill="none" stroke="black" points="821.72,-670.58 825.14,-660.55 816.21,-666.25 821.72,-670.58"/>
<text text-anchor="middle" x="749.26" y="-748.6" font-family="Roboto" font-size="8.00"> multi&#45;table</text>
<text text-anchor="middle" x="749.26" y="-739.6" font-family="Roboto" font-size="8.00">inheritance</text>
</g>
<!-- member_models_Profile -->
<g id="node7" class="node">
<title>member_models_Profile</title>
<polygon fill="white" stroke="transparent" points="971.76,-497 971.76,-715 1190.76,-715 1190.76,-497 971.76,-497"/>
<polygon fill="#1b563f" stroke="transparent" points="973.26,-693 973.26,-714 1190.26,-714 1190.26,-693 973.26,-693"/>
<text text-anchor="start" x="1049.26" y="-702" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1059.26" y="-702" font-family="Roboto" font-weight="bold" font-size="10.00" fill="white"> &#160;&#160;&#160;Profile &#160;&#160;&#160;</text>
<text text-anchor="start" x="975.26" y="-685.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="985.26" y="-685.6" font-family="Roboto" font-weight="bold" font-size="8.00">id</text>
<text text-anchor="start" x="993.26" y="-685.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1079.26" y="-685.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1089.26" y="-685.6" font-family="Roboto" font-weight="bold" font-size="8.00">AutoField</text>
<text text-anchor="start" x="1127.26" y="-685.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="975.26" y="-672.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="985.26" y="-672.6" font-family="Roboto" font-weight="bold" font-size="8.00">user</text>
<text text-anchor="start" x="1003.26" y="-672.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1079.26" y="-672.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1089.26" y="-672.6" font-family="Roboto" font-weight="bold" font-size="8.00">OneToOneField (id)</text>
<text text-anchor="start" x="1165.26" y="-672.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="975.26" y="-659.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="985.26" y="-659.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">address</text>
<text text-anchor="start" x="1013.26" y="-659.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1079.26" y="-659.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1089.26" y="-659.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">CharField</text>
<text text-anchor="start" x="1124.26" y="-659.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="975.26" y="-646.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="985.26" y="-646.6" font-family="Roboto" font-size="8.00">department</text>
<text text-anchor="start" x="1027.26" y="-646.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1079.26" y="-646.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1089.26" y="-646.6" font-family="Roboto" font-size="8.00">CharField</text>
<text text-anchor="start" x="1124.26" y="-646.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="975.26" y="-633.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="985.26" y="-633.6" font-family="Roboto" font-size="8.00">email_confirmed</text>
<text text-anchor="start" x="1044.26" y="-633.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1079.26" y="-633.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1089.26" y="-633.6" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="1135.26" y="-633.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="975.26" y="-620.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="985.26" y="-620.6" font-family="Roboto" font-size="8.00">last_report</text>
<text text-anchor="start" x="1023.26" y="-620.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1079.26" y="-620.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1089.26" y="-620.6" font-family="Roboto" font-size="8.00">DateTimeField</text>
<text text-anchor="start" x="1141.26" y="-620.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="975.26" y="-607.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="985.26" y="-607.6" font-family="Roboto" font-size="8.00">ml_art_registration</text>
<text text-anchor="start" x="1052.26" y="-607.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1079.26" y="-607.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1089.26" y="-607.6" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="1135.26" y="-607.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="975.26" y="-594.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="985.26" y="-594.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">ml_events_registration</text>
<text text-anchor="start" x="1065.26" y="-594.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1079.26" y="-594.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1089.26" y="-594.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">CharField</text>
<text text-anchor="start" x="1124.26" y="-594.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="975.26" y="-581.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="985.26" y="-581.6" font-family="Roboto" font-size="8.00">ml_sport_registration</text>
<text text-anchor="start" x="1060.26" y="-581.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1079.26" y="-581.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1089.26" y="-581.6" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="1135.26" y="-581.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="975.26" y="-568.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="985.26" y="-568.6" font-family="Roboto" font-size="8.00">paid</text>
<text text-anchor="start" x="1001.26" y="-568.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1079.26" y="-568.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1089.26" y="-568.6" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="1135.26" y="-568.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="975.26" y="-555.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="985.26" y="-555.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">phone_number</text>
<text text-anchor="start" x="1040.26" y="-555.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1079.26" y="-555.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1089.26" y="-555.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">PhoneNumberField</text>
<text text-anchor="start" x="1159.26" y="-555.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="975.26" y="-542.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="985.26" y="-542.6" font-family="Roboto" font-size="8.00">promotion</text>
<text text-anchor="start" x="1021.26" y="-542.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1079.26" y="-542.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1089.26" y="-542.6" font-family="Roboto" font-size="8.00">PositiveSmallIntegerField</text>
<text text-anchor="start" x="1178.26" y="-542.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="975.26" y="-529.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="985.26" y="-529.6" font-family="Roboto" font-size="8.00">registration_valid</text>
<text text-anchor="start" x="1045.26" y="-529.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1079.26" y="-529.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1089.26" y="-529.6" font-family="Roboto" font-size="8.00">BooleanField</text>
<text text-anchor="start" x="1135.26" y="-529.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="975.26" y="-516.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="985.26" y="-516.6" font-family="Roboto" font-size="8.00">report_frequency</text>
<text text-anchor="start" x="1046.26" y="-516.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1079.26" y="-516.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1089.26" y="-516.6" font-family="Roboto" font-size="8.00">PositiveSmallIntegerField</text>
<text text-anchor="start" x="1178.26" y="-516.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="975.26" y="-503.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="985.26" y="-503.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">section</text>
<text text-anchor="start" x="1010.26" y="-503.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1079.26" y="-503.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<text text-anchor="start" x="1089.26" y="-503.6" font-family="Roboto" font-size="8.00" fill="#7b7b7b">CharField</text>
<text text-anchor="start" x="1124.26" y="-503.6" font-family="Roboto" font-size="8.00"> &#160;&#160;&#160;</text>
<polygon fill="none" stroke="black" points="971.76,-497 971.76,-715 1190.76,-715 1190.76,-497 971.76,-497"/>
</g>
<!-- member_models_Profile&#45;&gt;django_contrib_auth_models_User -->
<g id="edge11" class="edge">
<title>member_models_Profile&#45;&gt;django_contrib_auth_models_User</title>
<path fill="none" stroke="black" d="M1010.97,-492.62C1002.57,-480.41 993.9,-468.32 985.26,-457 972.23,-439.93 955.81,-421.8 943.77,-409.03"/>
<text text-anchor="middle" x="1020.26" y="-464.1" font-family="Roboto" font-size="8.00"> user (profile)</text>
</g>
<!-- member_models_Club&#45;&gt;member_models_Club -->
<g id="edge12" class="edge">
<title>member_models_Club&#45;&gt;member_models_Club</title>
<path fill="none" stroke="black" d="M779.77,-93.53C786.05,-90.32 789.76,-85.97 789.76,-80.5 789.76,-73.05 782.88,-67.69 772.02,-64.43"/>
<ellipse fill="black" stroke="black" cx="775.74" cy="-95.11" rx="4" ry="4"/>
<text text-anchor="middle" x="823.26" y="-78.6" font-family="Roboto" font-size="8.00"> parent_club (club)</text>
</g>
<!-- member_models_Membership&#45;&gt;member_models_Club -->
<g id="edge14" class="edge">
<title>member_models_Membership&#45;&gt;member_models_Club</title>
<path fill="none" stroke="black" d="M863.76,-543.26C864.15,-516.37 862.46,-484.73 855.26,-457 826.89,-347.74 762.07,-234.51 714.72,-161.34"/>
<ellipse fill="black" stroke="black" cx="863.67" cy="-547.45" rx="4" ry="4"/>
<text text-anchor="middle" x="841.26" y="-318.6" font-family="Roboto" font-size="8.00"> club (membership)</text>
</g>
<!-- member_models_Membership&#45;&gt;permission_models_Role -->
<g id="edge15" class="edge">
<title>member_models_Membership&#45;&gt;permission_models_Role</title>
<path fill="none" stroke="black" d="M816.49,-545.05C801.23,-526.63 782.92,-507.44 763.26,-493 746.89,-480.98 735.35,-489.62 721.26,-475 705.92,-459.09 697.73,-435.03 693.49,-416.91"/>
<ellipse fill="black" stroke="black" cx="819.01" cy="-548.15" rx="4" ry="4"/>
<ellipse fill="black" stroke="black" cx="692.65" cy="-412.96" rx="4" ry="4"/>
<text text-anchor="middle" x="757.26" y="-464.1" font-family="Roboto" font-size="8.00"> roles (membership)</text>
</g>
<!-- member_models_Membership&#45;&gt;django_contrib_auth_models_User -->
<g id="edge13" class="edge">
<title>member_models_Membership&#45;&gt;django_contrib_auth_models_User</title>
<path fill="none" stroke="black" d="M878.91,-543.46C893.51,-497.7 912.45,-438.39 921.69,-409.44"/>
<ellipse fill="black" stroke="black" cx="877.63" cy="-547.44" rx="4" ry="4"/>
<text text-anchor="middle" x="943.76" y="-464.1" font-family="Roboto" font-size="8.00"> user (memberships)</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

370
docs/api/activity.rst Normal file
View File

@ -0,0 +1,370 @@
API Activités
=============
Activité
--------
**Chemin :** `/api/activity/activity/ <https://note.crans.org/api/activity/activity/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Activity List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `Activity` objects, serialize it to JSON with the given serializer,\nthen render it on /api/activity/activity/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "ID"
},
"name": {
"type": "string",
"required": true,
"read_only": false,
"label": "Nom",
"max_length": 255
},
"description": {
"type": "string",
"required": true,
"read_only": false,
"label": "Description"
},
"location": {
"type": "string",
"required": false,
"read_only": false,
"label": "Lieu",
"help_text": "Lieu o\u00f9 l'activit\u00e9 est organis\u00e9e, par exemple la Kfet.",
"max_length": 255
},
"date_start": {
"type": "datetime",
"required": true,
"read_only": false,
"label": "Date de d\u00e9but"
},
"date_end": {
"type": "datetime",
"required": true,
"read_only": false,
"label": "Date de fin"
},
"valid": {
"type": "boolean",
"required": false,
"read_only": false,
"label": "Valide"
},
"open": {
"type": "boolean",
"required": false,
"read_only": false,
"label": "Ouvrir"
},
"activity_type": {
"type": "field",
"required": true,
"read_only": false,
"label": "Type"
},
"creater": {
"type": "field",
"required": true,
"read_only": false,
"label": "Utilisateur"
},
"organizer": {
"type": "field",
"required": true,
"read_only": false,
"label": "Organisateur",
"help_text": "Le club qui organise l'activit\u00e9. Les co\u00fbts d'invitation iront pour ce club."
},
"attendees_club": {
"type": "field",
"required": true,
"read_only": false,
"label": "Club attendu",
"help_text": "Club qui est autoris\u00e9 \u00e0 rejoindre l'activit\u00e9. Tr\u00e8s souvent le club Kfet."
}
}
}
}
Filtres Django
~~~~~~~~~~~~~~
* ``name``
* ``description``
* ``activity_type``
* ``location``
* ``creater``
* ``organizer``
* ``attendees_club``
* ``date_start``
* ``date_end``
* ``valid``
* ``open``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``name`` (expression régulière)
* ``description`` (expression régulière)
* ``location`` (expression régulière)
* ``creater__last_name`` (expression régulière)
* ``creater__first_name`` (expression régulière)
* ``creater__email`` (expression régulière)
* ``creater__note__alias__name`` (expression régulière)
* ``creater__note__alias__normalized_name`` (expression régulière)
* ``organizer__name`` (expression régulière)
* ``organizer__email`` (expression régulière)
* ``organizer__note__alias__name`` (expression régulière)
* ``organizer__note__alias__normalized_name`` (expression régulière)
* ``attendees_club__name`` (expression régulière)
* ``attendees_club__email`` (expression régulière)
* ``attendees_club__note__alias__name`` (expression régulière)
* ``attendees_club__note__alias__normalized_name`` (expression régulière)
Type d'activité
---------------
**Chemin :** `/api/activity/type/ <https://note.crans.org/api/activity/type/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Activity Type List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `ActivityType` objects, serialize it to JSON with the given serializer,\nthen render it on /api/activity/type/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "ID"
},
"name": {
"type": "string",
"required": true,
"read_only": false,
"label": "Nom",
"max_length": 255
},
"manage_entries": {
"type": "boolean",
"required": false,
"read_only": false,
"label": "G\u00e9rer les entr\u00e9es",
"help_text": "Activer le support des entr\u00e9es pour cette activit\u00e9."
},
"can_invite": {
"type": "boolean",
"required": false,
"read_only": false,
"label": "Peut inviter"
},
"guest_entry_fee": {
"type": "integer",
"required": false,
"read_only": false,
"label": "Cotisation de l'entr\u00e9e invit\u00e9",
"min_value": 0,
"max_value": 2147483647
}
}
}
}
Filtres Django
~~~~~~~~~~~~~~
* ``name``
* ``manage_entries``
* ``can_invite``
* ``guest_entry_fee``
Invité
------
**Chemin :** `/api/activity/guest/ <https://note.crans.org/api/activity/guest/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Guest List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `Guest` objects, serialize it to JSON with the given serializer,\nthen render it on /api/activity/guest/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "ID"
},
"last_name": {
"type": "string",
"required": true,
"read_only": false,
"label": "Nom de famille",
"max_length": 255
},
"first_name": {
"type": "string",
"required": true,
"read_only": false,
"label": "Pr\u00e9nom",
"max_length": 255
},
"activity": {
"type": "field",
"required": true,
"read_only": false,
"label": "Activity"
},
"inviter": {
"type": "field",
"required": true,
"read_only": false,
"label": "H\u00f4te"
}
}
}
}
Filtres Django
~~~~~~~~~~~~~~
* ``activity``
* ``activity__name``
* ``last_name``
* ``first_name``
* ``inviter``
* ``inviter__alias__name``
* ``inviter__alias__normalized_name``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``activity__name`` (expression régulière)
* ``last_name`` (expression régulière)
* ``first_name`` (expression régulière)
* ``inviter__user__email`` (expression régulière)
* ``inviter__alias__name`` (expression régulière)
* ``inviter__alias__normalized_name`` (expression régulière)
Entrée
------
**Chemin :** `/api/activity/entry/ <https://note.crans.org/api/activity/entry/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Entry List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `Entry` objects, serialize it to JSON with the given serializer,\nthen render it on /api/activity/entry/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "ID"
},
"time": {
"type": "datetime",
"required": false,
"read_only": false,
"label": "Heure d'entr\u00e9e"
},
"activity": {
"type": "field",
"required": true,
"read_only": false,
"label": "Activit\u00e9"
},
"note": {
"type": "field",
"required": true,
"read_only": false,
"label": "Note"
},
"guest": {
"type": "field",
"required": true,
"read_only": false,
"label": "Guest"
}
}
}
}
Filtres Django
~~~~~~~~~~~~~~
* ``activity``
* ``time``
* ``note``
* ``guest``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``activity__name`` (expression régulière)
* ``note__user__email`` (expression régulière)
* ``note__alias__name`` (expression régulière)
* ``note__alias__normalized_name`` (expression régulière)
* ``guest__last_name`` (expression régulière)
* ``guest__first_name`` (expression régulière)

157
docs/api/basic.rst Normal file
View File

@ -0,0 +1,157 @@
API générale
============
Utilisateur
-----------
**Chemin :** `/api/user/ <https://note.crans.org/api/user/>`_
Options
~~~~~~~
.. code:: json
{
"name": "User List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `User` objects, serialize it to JSON with the given serializer,\nthen render it on /api/user/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "ID"
},
"last_login": {
"type": "datetime",
"required": false,
"read_only": false,
"label": "Derni\u00e8re connexion"
},
"is_superuser": {
"type": "boolean",
"required": false,
"read_only": false,
"label": "Statut super-utilisateur",
"help_text": "Pr\u00e9cise que l'utilisateur poss\u00e8de toutes les permissions sans les assigner explicitement."
},
"username": {
"type": "string",
"required": true,
"read_only": false,
"label": "Pseudo",
"help_text": "Requis. 150 caract\u00e8res maximum. Uniquement des lettres, nombres et les caract\u00e8res \u00ab\u00a0@\u00a0\u00bb, \u00ab\u00a0.\u00a0\u00bb, \u00ab\u00a0+\u00a0\u00bb, \u00ab\u00a0-\u00a0\u00bb et \u00ab\u00a0_\u00a0\u00bb.",
"max_length": 150
},
"first_name": {
"type": "string",
"required": false,
"read_only": false,
"label": "Pr\u00e9nom",
"max_length": 30
},
"last_name": {
"type": "string",
"required": false,
"read_only": false,
"label": "Nom de famille",
"max_length": 150
},
"email": {
"type": "email",
"required": false,
"read_only": false,
"label": "Adresse \u00e9lectronique",
"max_length": 254
},
"is_staff": {
"type": "boolean",
"required": false,
"read_only": false,
"label": "Statut \u00e9quipe",
"help_text": "Pr\u00e9cise si l'utilisateur peut se connecter \u00e0 ce site d'administration."
},
"is_active": {
"type": "boolean",
"required": false,
"read_only": false,
"label": "Actif",
"help_text": "Pr\u00e9cise si l'utilisateur doit \u00eatre consid\u00e9r\u00e9 comme actif. D\u00e9cochez ceci plut\u00f4t que de supprimer le compte."
},
"date_joined": {
"type": "datetime",
"required": false,
"read_only": false,
"label": "Date d'inscription"
}
}
}
}
Filtres Django
~~~~~~~~~~~~~~
* ``id``
* ``username``
* ``first_name``
* ``last_name``
* ``email``
* ``is_superuser``
* ``is_staff``
* ``is_active``
* ``note__alias__name``
* ``note__alias__normalized_name``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``note__alias`` (expression régulière, cherche en priorité les alias les plus proches, puis cherche les alias normalisés)
* ``last_name`` (expression régulière)
* ``first_name`` (expression régulière)
Type de contenu
---------------
**Chemin :** `/api/models/ <https://note.crans.org/api/models/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Content Type List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `User` objects, serialize it to JSON with the given serializer,\nthen render it on /api/models/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
]
}
Filtres Django
~~~~~~~~~~~~~~
* ``id``
* ``app_label``
* ``model``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``app_label`` (expression régulière)
* ``model`` (expression régulière)

214
docs/api/index.rst Normal file
View File

@ -0,0 +1,214 @@
API
===
.. toctree::
:maxdepth: 2
:caption: Applications
activity
basic
logs
member
note
permission
treasury
wei
La NoteKfet2020 dispose d'une API REST. Elle est accessible sur `/api/ <https://note.crans.org/api/>`_.
Elle supporte les requêtes GET, POST, HEAD, PUT, PATCH et DELETE (peut varier selon les pages).
Pages de l'API
--------------
Il suffit d'ajouter le préfixe ``/api/`` pour arriver sur ces pages.
* `models <basic#type-de-contenu>`_ : liste des différents modèles enregistrés en base de données
* `user <basic#utilisateur>`_ : liste des différents utilisateurs enregistrés
* `members/profile <member#profil-utilisateur>`_ : liste des différents profils associés à des utilisateurs
* `members/club <member#club>`_ : liste des différents clubs enregistrés
* `members/membership <member#adhesion>`_ : liste des adhésions enregistrées
* `activity/activity <activity#activite>`_ : liste des activités recensées
* `activity/type <activity#type-d-activite>`_ : liste des différents types d'activités : pots, soirées de club, ...
* `activity/guest <activity#invite>`_ : liste des personnes invitées lors d'une activité
* `activity/entry <activity#entree>`_ : liste des entrées effectuées lors des activités
* `note/note <note#note>`_ : liste des notes enregistrées
* `note/alias <note#alias>`_ : liste des alias enregistrés
* `note/consumer <note#consommateur>`_ : liste des alias enregistrés avec leur note associée
* `note/transaction/category <note#categorie-de-transaction>`_ : liste des différentes catégories de boutons : soft, alcool, ...
* `note/transaction/transaction <note#transaction>`_ : liste des transactions effectuées
* `note/transaction/template <note#modele-de-transaction>`_ : liste des boutons enregistrés
* `treasury/invoice <treasury#facture>`_ : liste des factures générées
* `treasury/product <treasury#produit>`_ : liste des produits associés à des factures
* `treasury/remittance_type <treasury#type-de-remise>`_ : liste des types de remises supportés : chèque
* `treasury/remittance <treasury#remise>`_ : liste des différentes remises enregistrées
* `treasury/remittance <treasury#remise>`_ : liste des crédits de la Société générale enregistrés
* `permission/permission <permission#permission>`_ : liste de toutes les permissions enregistrées
* `permission/roles <permission#permissions-par-roles>`_ : liste des permissions octroyées pour chacun des rôles
* `logs <logs#journal-de-modification>`_ : liste des modifications enregistrées en base de données
* `wei/club <wei#wei>`_ : liste des WEI
* `wei/bus <wei#bus>`_ : liste des bus de tous les WEI
* `wei/team <wei#equipe-de-bus>`_ : liste des équipes de tous les WEI
* `wei/role <wei#role-au-wei>`_ : liste des rôles possibles pour le WEI
* `wei/registration <wei#participation-au-wei>`_ : liste de toutes les inscriptions à un WEI
* `wei/membership <wei#adhesion-au-wei>`_ : liste des adhésions compètes à un WEI
Utilisation de l'API
--------------------
La page ``/api/<model>/`` affiche la liste de tous les éléments enregistrés. La page ``/api/<model>/<pk>/`` affiche
les attributs d'un objet uniquement.
L'affichage des données peut se faire sous deux formes : via une interface HTML propre ou directement en affichant
le JSON brut. Le changement peut se faire en ajoutant en paramètre de l'URL ``format=json`` ou ``format=api``, ou bien
en plaçant en en-tête de la requête ``Accept: application/json`` ou ``Accept: text/html``.
L'API Web propose des formulaires facilitant l'ajout et la modification d'éléments.
S'authentifier
~~~~~~~~~~~~~~
L'authentification peut se faire soit par session en se connectant via la page de connexion classique,
soit via un jeton d'authentification. Le jeton peut se récupérer via la page de son propre compte, en cliquant
sur le bouton « `Accès API <https://note.crans.org/accounts/manage-auth-token/>`_ ». Il peut être révoqué et regénéré
en un clic.
Pour s'authentifier via ce jeton, il faut ajouter l'en-tête ``Authorization: Token <TOKEN>`` aux paramètres HTTP.
En s'authentifiant par cette méthode, les masques de droit sont ignorés, les droits maximaux sont accordés.
GET
~~~
Une requête GET affiche un ou des éléments. Si on veut la liste de tous les éléments d'un modèle, la réponse
est de cette forme :
.. code:: json
{
"count": "<COUNT>",
"next": "/api/<MODEL>/?page=<NEXT_PAGE>",
"previous": "/api/<MODEL>/?page=<NEXT_PAGE>",
"results": [ ]
}
``<COUNT>`` est le nombre d'éléments trouvés. La page n'affiche les informations que 20 par 20 pour ne pas
augmenter inutilement la taille de la réponse. Les champs ``next`` et ``previous`` contiennent les URL des pages
suivantes et précédentes (``null`` si première ou dernière page). Le champ ``results`` contient enfin l'ensemble des
objets trouvés, au format JSON.
Certaines pages disposent de filtres, permettant de sélectionner les objets recherchés. Par exemple, il est possible
de chercher une note d'un certain type matchant avec un certain alias.
Trois types de filtres sont implémentés :
* Les filtres Django, permettant d'ajouter ``?key=value`` dans l'URL pour filtrer les objets ayant ``value`` comme
valeur pour la clé ``key`` ;
* Les filtres de recherche, permettant une recherche plus souple notamment par expressions régulières ou contenance,
et permet aussi de chercher parmi plusieurs clés à partir d'un champ ``search`` dans l'URL ;
* Les filtres de tri, qui ne filtrent pas réellement mais changent l'ordre. En ajoutant ``?ordering=key`` dans l'URL,
on trie les résultats selon la clé ``key`` dans l'ordre croissant, et ``?ordering=-key`` trie dans l'ordre
décroissant.
Les filtres disponibles sont indiqués sur chacune des pages de documentation.
Le résultat est déjà par défaut filtré par droits : seuls les éléments que l'utilisateur à le droit de voir sont affichés.
Cela est possible grâce à la structure des permissions, générant justement des filtres de requêtes de base de données.
Une requête à l'adresse ``/api/<model>/pk/`` affiche directement les informations du modèle demandé au format JSON.
POST
~~~~
Une requête POST permet d'ajouter des éléments. Cette requête n'est possible que sur la page ``/api/<model>/``,
la requête POST n'est pas supportée sur les pages de détails (car cette requête permet ... l'ajout).
Des exceptions sont faites sur certaines pages : les pages de logs et de contenttypes sont en lecture uniquement.
Les formats supportés sont multiples : ``application/json``, ``application/x-www-url-encoded``, ``multipart/form-data``.
Cela facilite l'envoi de requêtes. Le module construit ensuite l'instance du modèle et le sauvegarde dans la base de
données. L'application ``permission`` s'assure que l'utilisateur à le droit de faire ce type de modification. La réponse
renvoyée est l'objet enregistré au format JSON si l'ajout s'est bien déroulé, sinon un message d'erreur au format JSON.
PATCH
~~~~~
Une requête PATCH permet de modifier un élément. Ce type de requête n'est disponible que sur la page de détails d'un
élément : ``/api/<model>/pk/``.
Comme pour la requête POST, les formats supportés sont multiples : ``application/json``,
``application/x-www-url-encoded``, ``multipart/form-data``.
Il n'est pas utile d'indiquer tous les champs du modèle : seuls ceux qui sont à modifier suffisent.
Attention : pour les modèles polymorphiques (``Note``, ``Transaction``), il faut toujours spécifier le type de modèle
pour que l'API arrive à s'y retrouver. Par exemple, si on veut rendre la transaction n°42 non valide, on effectue une
requête ``PATCH`` sur ``/api/note/transaction/transaction/42/`` avec les données suivantes :
.. code:: json
{
"valid": false,
"resourcetype": "RecurrentTransaction"
}
PUT
~~~
Une requête PUT permet de remplacer un élément. Ce type de requête n'est disponible que sur la page de détails d'un
élément : ``/api/<model>/pk/``.
Comme pour les requêtes POST ou PATCH, les formats supportés sont multiples : ``application/json``,
``application/x-www-url-encoded``, ``multipart/form-data``.
Contrairement à la requête PATCH, l'intégralité du modèle est remplacé. L'ancien modèle est détruit, on en recrée un
nouveau avec la même clé primaire. Le fonctionnement est similaire à une requête POST.
DELETE
~~~~~~
Une requête de type DELETE permet de supprimer un élément. Ce type de requête n'est disponible que sur la page de
détails d'un élément : ``/api/<model>/pk/``.
Aucune donnée n'est nécessaire. Le module de permissions vérifiera que la suppression est possible. Une erreur
est sinon renvoyée.
OPTIONS
~~~~~~~
Une reqête OPTIONS affiche l'ensemble des opérations possibles sur un modèle ou une instance. Prototype d'une réponse :
.. code:: json
{
"name": "<NAME>",
"description": "<DESCRIPTION>",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"<METHOD>": {
"<FIELD_NAME>": {
"type": "<TYPE>",
"required": "<REQUIRED>",
"read_only": "<READ_ONLY>",
"label": "<LABEL>"
}
}
}
}
* ``<METHOD>`` est le type de requête HTTP supporté (pour modification, inclus dans {``POST``, ``PUT``, ``PATCH``}).
* ``<FIELD_NAME>`` est le nom du champ dans le modèle concerné (exemple : ``id``)
* ``<TYPE>`` représente le type de données : ``integer``, ``string``, ``date``, ``choice``, ``field`` (pour les clés étrangères), ...
* ``<REQUIRED>`` est un booléen indiquant si le champ est requis dans le modèle ou s'il peut être nul/vide.
* ``<READ_ONLY>`` est un booléen indiquant si le champ est accessible en lecture uniquement.
* ``<LABEL>`` représente le label du champ, son nom traduit, qui s'affiche dans le formulaire accessible sur l'API Web.
Des contraintes peuvent s'ajouter à cela selon les champs : taille maximale de chaînes de caractères, valeurs minimales
et maximales pour les entiers ...

42
docs/api/logs.rst Normal file
View File

@ -0,0 +1,42 @@
API Logs
========
Journal de modification
-----------------------
**Chemin :** `/api/logs/ <https://note.crans.org/api/logs/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Changelog List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `Changelog` objects, serialize it to JSON with the given serializer,\nthen render it on /api/logs/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
]
}
Filtres Django
~~~~~~~~~~~~~~
* ``model``
* ``action``
* ``instance_pk``
* ``user``
* ``ip``
Tris possible
~~~~~~~~~~~~~
* ``timestamp``
* ``id``

476
docs/api/member.rst Normal file
View File

@ -0,0 +1,476 @@
API Membres
===========
Profil utilisateur
------------------
**Chemin :** `/api/members/profile/ <https://note.crans.org/api/members/profile/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Profile List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `Profile` objects, serialize it to JSON with the given serializer,\nthen render it on /api/members/profile/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "ID"
},
"phone_number": {
"type": "string",
"required": false,
"read_only": false,
"label": "Num\u00e9ro de t\u00e9l\u00e9phone",
"max_length": 50
},
"section": {
"type": "string",
"required": false,
"read_only": false,
"label": "Section",
"help_text": "e.g. \"1A0\", \"9A\u2665\", \"SAPHIRE\"",
"max_length": 255
},
"department": {
"type": "choice",
"required": true,
"read_only": false,
"label": "D\u00e9partement",
"choices": [
{
"value": "A0",
"display_name": "Informatique (A0)"
},
{
"value": "A1",
"display_name": "Math\u00e9matiques (A1)"
},
{
"value": "A2",
"display_name": "Chimie (A''2)"
},
{
"value": "A'2",
"display_name": "Physique appliqu\u00e9e (A'2)"
},
{
"value": "A3",
"display_name": "Biologie (A3)"
},
{
"value": "B1234",
"display_name": "SAPHIRE (B1234)"
},
{
"value": "B1",
"display_name": "M\u00e9canique (B1)"
},
{
"value": "B2",
"display_name": "G\u00e9nie civil (B2)"
},
{
"value": "B3",
"display_name": "G\u00e9nie m\u00e9canique (B3)"
},
{
"value": "B4",
"display_name": "EEA (B4)"
},
{
"value": "C",
"display_name": "Design (C)"
},
{
"value": "D2",
"display_name": "\u00c9conomie-gestion (D2)"
},
{
"value": "D3",
"display_name": "Sciences sociales (D3)"
},
{
"value": "E",
"display_name": "Anglais (E)"
},
{
"value": "EXT",
"display_name": "Externe (EXT)"
}
]
},
"promotion": {
"type": "integer",
"required": false,
"read_only": false,
"label": "Promotion",
"help_text": "Ann\u00e9e d'entr\u00e9e dans l'\u00e9cole (None si non-\u00e9tudiant\u00b7e de l'ENS)",
"min_value": 0,
"max_value": 32767
},
"address": {
"type": "string",
"required": false,
"read_only": false,
"label": "Adresse",
"max_length": 255
},
"paid": {
"type": "boolean",
"required": false,
"read_only": false,
"label": "Pay\u00e9",
"help_text": "Indique si l'utilisateur per\u00e7oit un salaire."
},
"ml_events_registration": {
"type": "choice",
"required": false,
"read_only": false,
"label": "S'inscrire sur la liste de diffusion pour rester inform\u00e9 des \u00e9v\u00e9nements sur le campus (1 mail par semaine)",
"choices": [
{
"value": "",
"display_name": "Non"
},
{
"value": "fr",
"display_name": "Oui (les recevoir en fran\u00e7ais)"
},
{
"value": "en",
"display_name": "Oui (les recevoir en anglais)"
}
]
},
"ml_sport_registration": {
"type": "boolean",
"required": false,
"read_only": false,
"label": "S'inscrire sur la liste de diffusion pour rester inform\u00e9 des actualit\u00e9s sportives sur le campus (1 mail par semaine)"
},
"ml_art_registration": {
"type": "boolean",
"required": false,
"read_only": false,
"label": "S'inscrire sur la liste de diffusion pour rester inform\u00e9 des actualit\u00e9s artistiques sur le campus (1 mail par semaine)"
},
"report_frequency": {
"type": "integer",
"required": false,
"read_only": false,
"label": "Fr\u00e9quence des rapports (en jours)",
"min_value": 0,
"max_value": 32767
},
"last_report": {
"type": "datetime",
"required": false,
"read_only": false,
"label": "Date de dernier rapport"
},
"email_confirmed": {
"type": "boolean",
"required": false,
"read_only": false,
"label": "Adresse email confirm\u00e9e"
},
"registration_valid": {
"type": "boolean",
"required": false,
"read_only": false,
"label": "Inscription valide"
},
"user": {
"type": "field",
"required": false,
"read_only": true,
"label": "User"
}
}
}
}
Filtres Django
~~~~~~~~~~~~~~
* ``user``
* ``user__first_name``
* ``user__last_name``
* ``user__username``
* ``user__email``
* ``user__note__alias__name``
* ``user__note__alias__normalized_name``
* ``phone_number``
* ``section``
* ``department``
* ``promotion``
* ``address``
* ``paid``
* ``ml_events_registration``
* ``ml_sport_registration``
* ``ml_art_registration``
* ``report_frequency``
* ``email_confirmed``
* ``registration_valid``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``user__first_name`` (expression régulière)
* ``user__last_name`` (expression régulière)
* ``user__username`` (expression régulière)
* ``user__email`` (expression régulière)
* ``user__note__alias__name`` (expression régulière)
* ``user__note__alias__normalized_name`` (expression régulière)
Club
----
**Chemin :** `/api/members/club/ <https://note.crans.org/api/members/club/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Club List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `Club` objects, serialize it to JSON with the given serializer,\nthen render it on /api/members/club/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "ID"
},
"name": {
"type": "string",
"required": true,
"read_only": false,
"label": "Nom",
"max_length": 255
},
"email": {
"type": "email",
"required": true,
"read_only": false,
"label": "Courriel",
"max_length": 254
},
"require_memberships": {
"type": "boolean",
"required": false,
"read_only": false,
"label": "N\u00e9cessite des adh\u00e9sions",
"help_text": "D\u00e9cochez si ce club n'utilise pas d'adh\u00e9sions."
},
"membership_fee_paid": {
"type": "integer",
"required": false,
"read_only": false,
"label": "Cotisation pour adh\u00e9rer (normalien \u00e9l\u00e8ve)",
"min_value": 0,
"max_value": 2147483647
},
"membership_fee_unpaid": {
"type": "integer",
"required": false,
"read_only": false,
"label": "Cotisation pour adh\u00e9rer (normalien \u00e9tudiant)",
"min_value": 0,
"max_value": 2147483647
},
"membership_duration": {
"type": "integer",
"required": false,
"read_only": false,
"label": "Dur\u00e9e de l'adh\u00e9sion",
"help_text": "La dur\u00e9e maximale (en jours) d'une adh\u00e9sion (NULL = infinie).",
"min_value": 0,
"max_value": 2147483647
},
"membership_start": {
"type": "date",
"required": false,
"read_only": false,
"label": "D\u00e9but de l'adh\u00e9sion",
"help_text": "Date \u00e0 partir de laquelle les adh\u00e9rents peuvent renouveler leur adh\u00e9sion."
},
"membership_end": {
"type": "date",
"required": false,
"read_only": false,
"label": "Fin de l'adh\u00e9sion",
"help_text": "Date maximale d'une fin d'adh\u00e9sion, apr\u00e8s laquelle les adh\u00e9rents doivent la renouveler."
},
"parent_club": {
"type": "field",
"required": false,
"read_only": false,
"label": "Club parent"
}
}
}
}
Filtres Django
~~~~~~~~~~~~~~
* ``name``
* ``email``
* ``note__alias__name``
* ``note__alias__normalized_name``
* ``parent_club``
* ``parent_club__name``
* ``require_memberships``
* ``membership_fee_paid``
* ``membership_fee_unpaid``
* ``membership_duration``
* ``membership_start``
* ``membership_end``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``name`` (expression régulière)
* ``email`` (expression régulière)
* ``note__alias__name`` (expression régulière)
* ``note__alias__normalized_name`` (expression régulière)
Adhésion
--------
**Chemin :** `/api/members/membership/ <https://note.crans.org/api/members/membership/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Membership List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `Membership` objects, serialize it to JSON with the given serializer,\nthen render it on /api/members/membership/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "ID"
},
"date_start": {
"type": "date",
"required": false,
"read_only": false,
"label": "L'adh\u00e9sion commence le"
},
"date_end": {
"type": "date",
"required": false,
"read_only": false,
"label": "L'adh\u00e9sion finit le"
},
"fee": {
"type": "integer",
"required": true,
"read_only": false,
"label": "Cotisation",
"min_value": 0,
"max_value": 2147483647
},
"user": {
"type": "field",
"required": true,
"read_only": false,
"label": "Utilisateur"
},
"club": {
"type": "field",
"required": true,
"read_only": false,
"label": "Club"
},
"roles": {
"type": "field",
"required": true,
"read_only": false,
"label": "R\u00f4les"
}
}
}
}
Filtres Django
~~~~~~~~~~~~~~
* ``club__name``
* ``club__email``
* ``club__note__alias__name``
* ``club__note__alias__normalized_name``
* ``user__username``
* ``user__last_name``
* ``user__first_name``
* ``user__email``
* ``user__note__alias__name``
* ``user__note__alias__normalized_name``
* ``date_start``
* ``date_end``
* ``fee``
* ``roles``
Tris possible
~~~~~~~~~~~~~
* ``id``
* ``date_start``
* ``date_end``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``club__name`` (expression régulière)
* ``club__email`` (expression régulière)
* ``club__note__alias__name`` (expression régulière)
* ``club__note__alias__normalized_name`` (expression régulière)
* ``user__username`` (expression régulière)
* ``user__last_name`` (expression régulière)
* ``user__first_name`` (expression régulière)
* ``user__email`` (expression régulière)
* ``user__note__alias__name`` (expression régulière)
* ``user__note__alias__normalized_name`` (expression régulière)
* ``roles__name`` (expression régulière)

403
docs/api/note.rst Normal file
View File

@ -0,0 +1,403 @@
API Note
========
Note
----
**Chemin :** `/api/note/note/ <https://note.crans.org/api/note/note/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Note Polymorphic List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `Note` objects (with polymorhism),\nserialize it to JSON with the given serializer,\nthen render it on /api/note/note/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {}
}
}
Filtres Django
~~~~~~~~~~~~~~
* ``alias__name``
* ``polymorphic_ctype``
* ``is_active``
* ``balance``
* ``last_negative``
* ``created_at``
Tris possible
~~~~~~~~~~~~~
* ``alias__name``
* ``alias__normalized_name``
* ``balance``
* ``created_at``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``alias__normalized_name`` (expression régulière)
* ``alias__name`` (expression régulière)
* ``polymorphic_ctype__model`` (expression régulière)
* ``noteuser__user__last_name`` (expression régulière)
* ``noteuser__user__first_name`` (expression régulière)
* ``noteuser__user__email`` (expression régulière)
* ``noteuser__user__email`` (expression régulière)
* ``noteclub__club__email`` (expression régulière)
Alias
-----
**Chemin :** `/api/note/alias/ <https://note.crans.org/api/note/alias/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Alias List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `Alias` objects, serialize it to JSON with the given serializer,\nthen render it on /api/aliases/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "ID"
},
"name": {
"type": "string",
"required": true,
"read_only": false,
"label": "Nom",
"max_length": 255
},
"normalized_name": {
"type": "string",
"required": false,
"read_only": true,
"label": "Normalized name"
},
"note": {
"type": "field",
"required": true,
"read_only": false,
"label": "Note"
}
}
}
}
Filtres Django
~~~~~~~~~~~~~~
* ``note``
* ``note__noteuser__user``
* ``note__noteclub__club``
* ``note__polymorphic_ctype__model``
Tris possible
~~~~~~~~~~~~~
* ``name``
* ``normalized_name``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``alias`` (cherche en priorité les alias les plus proches, puis cherche les alias normalisés)
* ``normalized_name`` (expression régulière)
* ``name`` (expression régulière)
* ``note__polymorphic_ctype__model`` (expression régulière)
Consommateur
------------
**Chemin :** `/api/note/consumer/ <https://note.crans.org/api/note/consumer/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Consumer List",
"description": "",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
]
}
.. note::
Cette page est en lecture seule. Elle offre l'avantage de fournir directement les informations sur la note associée
à l'alias au lieu de l'identifiant uniquement, afin de minimiser les appels à l'API.
Filtres Django
~~~~~~~~~~~~~~
* ``alias`` (expression régulière, cherche en priorité les alias les plus proches, puis cherche les alias normalisés)
* ``note``
* ``note__noteuser__user``
* ``note__noteclub__club``
* ``note__polymorphic_ctype__model``
Tris possible
~~~~~~~~~~~~~
* ``name``
* ``normalized_name``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``normalized_name`` (expression régulière)
* ``name`` (expression régulière)
* ``note__polymorphic_ctype__model`` (expression régulière)
Catégorie de transaction
------------------------
**Chemin :** `/api/note/transaction/category/ <https://note.crans.org/api/note/transaction/category/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Template Category List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `TemplateCategory` objects, serialize it to JSON with the given serializer,\nthen render it on /api/note/transaction/category/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "ID"
},
"name": {
"type": "string",
"required": true,
"read_only": false,
"label": "Nom",
"max_length": 31
}
}
}
}
Filtres Django
~~~~~~~~~~~~~~
* ``name``
* ``templates``
* ``templates__name``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``name`` (expression régulière)
* ``templates__name`` (expression régulière)
Modèle de transaction
---------------------
**Chemin :** `/api/note/transaction/template/ <https://note.crans.org/api/note/transaction/template/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Transaction Template List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `TransactionTemplate` objects, serialize it to JSON with the given serializer,\nthen render it on /api/note/transaction/template/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "ID"
},
"name": {
"type": "string",
"required": true,
"read_only": false,
"label": "Nom",
"max_length": 255
},
"amount": {
"type": "integer",
"required": true,
"read_only": false,
"label": "Montant",
"min_value": 0,
"max_value": 2147483647
},
"display": {
"type": "boolean",
"required": false,
"read_only": false,
"label": "Afficher"
},
"highlighted": {
"type": "boolean",
"required": false,
"read_only": false,
"label": "Mis en avant"
},
"description": {
"type": "string",
"required": false,
"read_only": false,
"label": "Description",
"max_length": 255
},
"destination": {
"type": "field",
"required": true,
"read_only": false,
"label": "Destination"
},
"category": {
"type": "field",
"required": true,
"read_only": false,
"label": "Type"
}
}
}
}
Filtres Django
~~~~~~~~~~~~~~
* ``name``
* ``amount``
* ``display``
* ``category``
* ``category__name``
Tris possible
~~~~~~~~~~~~~
* ``amount``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``name`` (expression régulière)
* ``category__name`` (expression régulière)
Transaction
-----------
**Chemin :** `/api/note/transaction/transaction/ <https://note.crans.org/api/note/transaction/transaction/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Transaction List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `Transaction` objects, serialize it to JSON with the given serializer,\nthen render it on /api/note/transaction/transaction/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {}
}
}
Filtres Django
~~~~~~~~~~~~~~
* ``source``
* ``source_alias``
* ``source__alias__name``
* ``source__alias__normalized_name``
* ``destination``
* ``destination_alias``
* ``destination__alias__name``
* ``destination__alias__normalized_name``
* ``quantity``
* ``polymorphic_ctype``
* ``amount``
* ``created_at``
* ``valid``
* ``invalidity_reason``
Tris possible
~~~~~~~~~~~~~
* ``created_at``
* ``amount``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``reason`` (expression régulière)
* ``source_alias`` (expression régulière)
* ``source__alias__name`` (expression régulière)
* ``source__alias__normalized_name`` (expression régulière)
* ``destination_alias`` (expression régulière)
* ``destination__alias__name`` (expression régulière)
* ``destination__alias__normalized_name`` (expression régulière)
* ``invalidity_reason`` (expression régulière)

82
docs/api/permission.rst Normal file
View File

@ -0,0 +1,82 @@
API Permissions
===============
Permission
----------
**Chemin :** `/api/permission/permission/ <https://note.crans.org/api/permission/permission/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Permission List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `Permission` objects, serialize it to JSON with the given serializer,\nthen render it on /api/permission/permission/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
]
}
Filtres Django
~~~~~~~~~~~~~~
* ``model``
* ``type``
* ``query``
* ``mask``
* ``field``
* ``permanent``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``model__name`` (expression régulière)
* ``query`` (expression régulière)
* ``description`` (expression régulière)
Permissions par rôles
---------------------
**Chemin :** `/api/permission/roles/ <https://note.crans.org/api/permission/roles/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Role List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `RolePermission` objects, serialize it to JSON with the given serializer\nthen render it on /api/permission/roles/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
]
}
Filtres Django
~~~~~~~~~~~~~~
* ``name``
* ``permissions``
* ``for_club``
* ``memberships__user``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``name`` (expression régulière)
* ``for_club__name`` (expression régulière)

402
docs/api/treasury.rst Normal file
View File

@ -0,0 +1,402 @@
API Trésorerie
==============
Facture
-------
**Chemin :** `/api/treasury/invoice/ <https://note.crans.org/api/treasury/invoice/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Invoice List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `Invoice` objects, serialize it to JSON with the given serializer,\nthen render it on /api/treasury/invoice/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"id": {
"type": "integer",
"required": true,
"read_only": false,
"label": "Num\u00e9ro de facture",
"min_value": 0,
"max_value": 2147483647
},
"products": {
"type": "field",
"required": false,
"read_only": true,
"label": "Products"
},
"bde": {
"type": "choice",
"required": false,
"read_only": true,
"label": "BDE"
},
"object": {
"type": "string",
"required": true,
"read_only": false,
"label": "Objet",
"max_length": 255
},
"description": {
"type": "string",
"required": true,
"read_only": false,
"label": "Description"
},
"name": {
"type": "string",
"required": true,
"read_only": false,
"label": "Nom",
"max_length": 255
},
"address": {
"type": "string",
"required": true,
"read_only": false,
"label": "Adresse"
},
"date": {
"type": "date",
"required": false,
"read_only": false,
"label": "Date"
},
"acquitted": {
"type": "boolean",
"required": false,
"read_only": false,
"label": "Acquitt\u00e9e"
},
"locked": {
"type": "boolean",
"required": false,
"read_only": false,
"label": "Verrouill\u00e9e",
"help_text": "Une facture ne peut plus \u00eatre modifi\u00e9e si elle est verrouill\u00e9e."
},
"tex": {
"type": "string",
"required": false,
"read_only": false,
"label": "Fichier TeX source"
}
}
}
}
Filtres Django
~~~~~~~~~~~~~~
* ``bde``
* ``object``
* ``description``
* ``name``
* ``address``
* ``date``
* ``acquitted``
* ``locked``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``object`` (expression régulière)
* ``description`` (expression régulière)
* ``name`` (expression régulière)
* ``address`` (expression régulière)
Produit
-------
**Chemin :** `/api/treasury/product/ <https://note.crans.org/api/treasury/product/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Product List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `Product` objects, serialize it to JSON with the given serializer,\nthen render it on /api/treasury/product/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "ID"
},
"designation": {
"type": "string",
"required": true,
"read_only": false,
"label": "D\u00e9signation",
"max_length": 255
},
"quantity": {
"type": "integer",
"required": true,
"read_only": false,
"label": "Quantit\u00e9",
"min_value": 0,
"max_value": 2147483647
},
"amount": {
"type": "integer",
"required": true,
"read_only": false,
"label": "Prix unitaire",
"min_value": -2147483648,
"max_value": 2147483647
},
"invoice": {
"type": "field",
"required": true,
"read_only": false,
"label": "Facture"
}
}
}
}
Filtres Django
~~~~~~~~~~~~~~
* ``invoice``
* ``designation``
* ``quantity``
* ``amount``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``designation`` (expression régulière)
* ``invoice__object`` (expression régulière)
Type de remise
--------------
**Chemin :** `/api/treasury/remittance_type/ <https://note.crans.org/api/treasury/remittance_type/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Remittance Type List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `RemittanceType` objects, serialize it to JSON with the given serializer\nthen render it on /api/treasury/remittance_type/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "ID"
},
"note": {
"type": "field",
"required": true,
"read_only": false,
"label": "Note"
}
}
}
}
Filtres Django
~~~~~~~~~~~~~~
* ``note``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``note__special_type`` (expression régulière)
Remise
------
**Chemin :** `/api/treasury/remittance/ <https://note.crans.org/api/treasury/remittance/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Remittance List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `Remittance` objects, serialize it to JSON with the given serializer,\nthen render it on /api/treasury/remittance/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "ID"
},
"transactions": {
"type": "field",
"required": false,
"read_only": true,
"label": "Transactions"
},
"date": {
"type": "datetime",
"required": false,
"read_only": false,
"label": "Date"
},
"comment": {
"type": "string",
"required": true,
"read_only": false,
"label": "Commentaire",
"max_length": 255
},
"closed": {
"type": "boolean",
"required": false,
"read_only": false,
"label": "Ferm\u00e9e"
},
"remittance_type": {
"type": "field",
"required": true,
"read_only": false,
"label": "Type"
}
}
}
}
Filtres Django
~~~~~~~~~~~~~~
* ``date``
* ``remittance_type``
* ``comment``
* ``closed``
* ``transaction_proxies__transaction``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``remittance_type__note__special_type`` (expression régulière)
* ``comment`` (expression régulière)
Crédit de la société générale
-----------------------------
**Chemin :** `/api/treasury/soge_credit/ <https://note.crans.org/api/treasury/soge_credit/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Soge Credit List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `SogeCredit` objects, serialize it to JSON with the given serializer,\nthen render it on /api/treasury/soge_credit/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "ID"
},
"user": {
"type": "field",
"required": true,
"read_only": false,
"label": "Utilisateur"
},
"credit_transaction": {
"type": "field",
"required": false,
"read_only": false,
"label": "Transaction de cr\u00e9dit"
},
"transactions": {
"type": "field",
"required": true,
"read_only": false,
"label": "Transactions d'adh\u00e9sion"
}
}
}
}
Filtres Django
~~~~~~~~~~~~~~
* ``user``
* ``user__last_name``
* ``user__first_name``
* ``user__email``
* ``user__note__alias__name``
* ``user__note__alias__normalized_name``
* ``transactions``
* ``credit_transaction``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``user__last_name`` (expression régulière)
* ``user__first_name`` (expression régulière)
* ``user__email`` (expression régulière)
* ``user__note__alias__name`` (expression régulière)
* ``user__note__alias__normalized_name`` (expression régulière)

710
docs/api/wei.rst Normal file
View File

@ -0,0 +1,710 @@
API WEI
=======
Wei
---
**Chemin :** `/api/wei/club/ <https://note.crans.org/api/wei/club/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Wei Club List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `WEIClub` objects, serialize it to JSON with the given serializer,\nthen render it on /api/wei/club/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "ID"
},
"name": {
"type": "string",
"required": true,
"read_only": false,
"label": "Nom",
"max_length": 255
},
"email": {
"type": "email",
"required": true,
"read_only": false,
"label": "Courriel",
"max_length": 254
},
"require_memberships": {
"type": "boolean",
"required": false,
"read_only": false,
"label": "N\u00e9cessite des adh\u00e9sions",
"help_text": "D\u00e9cochez si ce club n'utilise pas d'adh\u00e9sions."
},
"membership_fee_paid": {
"type": "integer",
"required": false,
"read_only": false,
"label": "Cotisation pour adh\u00e9rer (normalien \u00e9l\u00e8ve)",
"min_value": 0,
"max_value": 2147483647
},
"membership_fee_unpaid": {
"type": "integer",
"required": false,
"read_only": false,
"label": "Cotisation pour adh\u00e9rer (normalien \u00e9tudiant)",
"min_value": 0,
"max_value": 2147483647
},
"membership_duration": {
"type": "integer",
"required": false,
"read_only": false,
"label": "Dur\u00e9e de l'adh\u00e9sion",
"help_text": "La dur\u00e9e maximale (en jours) d'une adh\u00e9sion (NULL = infinie).",
"min_value": 0,
"max_value": 2147483647
},
"membership_start": {
"type": "date",
"required": false,
"read_only": false,
"label": "D\u00e9but de l'adh\u00e9sion",
"help_text": "Date \u00e0 partir de laquelle les adh\u00e9rents peuvent renouveler leur adh\u00e9sion."
},
"membership_end": {
"type": "date",
"required": false,
"read_only": false,
"label": "Fin de l'adh\u00e9sion",
"help_text": "Date maximale d'une fin d'adh\u00e9sion, apr\u00e8s laquelle les adh\u00e9rents doivent la renouveler."
},
"year": {
"type": "integer",
"required": false,
"read_only": false,
"label": "Ann\u00e9e",
"min_value": 0,
"max_value": 2147483647
},
"date_start": {
"type": "date",
"required": true,
"read_only": false,
"label": "D\u00e9but"
},
"date_end": {
"type": "date",
"required": true,
"read_only": false,
"label": "Fin"
},
"parent_club": {
"type": "field",
"required": false,
"read_only": false,
"label": "Club parent"
}
}
}
}
Filtres Django
~~~~~~~~~~~~~~
* ``name``
* ``year``
* ``date_start``
* ``date_end``
* ``email``
* ``note__alias__name``
* ``note__alias__normalized_name``
* ``parent_club``
* ``parent_club__name``
* ``require_memberships``
* ``membership_fee_paid``
* ``membership_fee_unpaid``
* ``membership_duration``
* ``membership_start``
* ``membership_end``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``name`` (expression régulière)
* ``email`` (expression régulière)
* ``note__alias__name`` (expression régulière)
* ``note__alias__normalized_name`` (expression régulière)
Bus
---
**Chemin :** `/api/wei/bus/ <https://note.crans.org/api/wei/bus/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Bus List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `Bus` objects, serialize it to JSON with the given serializer,\nthen render it on /api/wei/bus/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "ID"
},
"name": {
"type": "string",
"required": true,
"read_only": false,
"label": "Nom",
"max_length": 255
},
"description": {
"type": "string",
"required": false,
"read_only": false,
"label": "Description"
},
"information_json": {
"type": "string",
"required": false,
"read_only": false,
"label": "Informations sur le questionnaire",
"help_text": "Informations sur le sondage pour les nouveaux membres, encod\u00e9es en JSON"
},
"wei": {
"type": "field",
"required": true,
"read_only": false,
"label": "WEI"
}
}
}
}
Filtres Django
~~~~~~~~~~~~~~
* ``name``
* ``wei``
* ``description``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``name`` (expression régulière)
* ``wei__name`` (expression régulière)
* ``description`` (expression régulière)
Équipe de bus
-------------
**Chemin :** `/api/wei/team/ <https://note.crans.org/api/wei/team/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Bus Team List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `BusTeam` objects, serialize it to JSON with the given serializer,\nthen render it on /api/wei/team/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "ID"
},
"name": {
"type": "string",
"required": true,
"read_only": false,
"label": "Nom",
"max_length": 255
},
"color": {
"type": "integer",
"required": true,
"read_only": false,
"label": "Couleur",
"help_text": "La couleur du T-Shirt, stock\u00e9 sous la forme de son \u00e9quivalent num\u00e9rique",
"min_value": 0,
"max_value": 2147483647
},
"description": {
"type": "string",
"required": false,
"read_only": false,
"label": "Description"
},
"bus": {
"type": "field",
"required": true,
"read_only": false,
"label": "Bus"
}
}
}
}
Filtres Django
~~~~~~~~~~~~~~
* ``name``
* ``bus``
* ``color``
* ``description``
* ``bus__wei``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``name`` (expression régulière)
* ``bus__name`` (expression régulière)
* ``bus__wei__name`` (expression régulière)
* ``description`` (expression régulière)
Rôle au wei
-----------
**Chemin :** `/api/wei/role/ <https://note.crans.org/api/wei/role/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Wei Role List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `WEIRole` objects, serialize it to JSON with the given serializer,\nthen render it on /api/wei/role/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "ID"
},
"name": {
"type": "string",
"required": true,
"read_only": false,
"label": "Nom",
"max_length": 255
},
"for_club": {
"type": "field",
"required": false,
"read_only": false,
"label": "S'applique au club"
},
"permissions": {
"type": "field",
"required": true,
"read_only": false,
"label": "Permissions"
}
}
}
}
Filtres Django
~~~~~~~~~~~~~~
* ``name``
* ``permissions``
* ``memberships``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``name`` (expression régulière)
Participant au wei
------------------
**Chemin :** `/api/wei/registration/ <https://note.crans.org/api/wei/registration/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Wei Registration List",
"description": "REST API View set.\nThe djangorestframework plugin will get all WEIRegistration objects, serialize it to JSON with the given serializer,\nthen render it on /api/wei/registration/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "ID"
},
"soge_credit": {
"type": "boolean",
"required": false,
"read_only": false,
"label": "Cr\u00e9dit de la Soci\u00e9t\u00e9 g\u00e9n\u00e9rale"
},
"caution_check": {
"type": "boolean",
"required": false,
"read_only": false,
"label": "Ch\u00e8que de caution donn\u00e9"
},
"birth_date": {
"type": "date",
"required": true,
"read_only": false,
"label": "Date de naissance"
},
"gender": {
"type": "choice",
"required": true,
"read_only": false,
"label": "Genre",
"choices": [
{
"value": "male",
"display_name": "Homme"
},
{
"value": "female",
"display_name": "Femme"
},
{
"value": "nonbinary",
"display_name": "Non-binaire"
}
]
},
"clothing_cut": {
"type": "choice",
"required": true,
"read_only": false,
"label": "Coupe de v\u00eatement",
"choices": [
{
"value": "male",
"display_name": "Homme"
},
{
"value": "female",
"display_name": "Femme"
}
]
},
"clothing_size": {
"type": "choice",
"required": true,
"read_only": false,
"label": "Taille de v\u00eatement",
"choices": [
{
"value": "XS",
"display_name": "XS"
},
{
"value": "S",
"display_name": "S"
},
{
"value": "M",
"display_name": "M"
},
{
"value": "L",
"display_name": "L"
},
{
"value": "XL",
"display_name": "XL"
},
{
"value": "XXL",
"display_name": "XXL"
}
]
},
"health_issues": {
"type": "string",
"required": false,
"read_only": false,
"label": "Probl\u00e8mes de sant\u00e9"
},
"emergency_contact_name": {
"type": "string",
"required": true,
"read_only": false,
"label": "Nom du contact en cas d'urgence",
"max_length": 255
},
"emergency_contact_phone": {
"type": "string",
"required": true,
"read_only": false,
"label": "T\u00e9l\u00e9phone du contact en cas d'urgence",
"max_length": 32
},
"first_year": {
"type": "boolean",
"required": false,
"read_only": false,
"label": "Premi\u00e8re ann\u00e9e",
"help_text": "Indique si l'utilisateur est nouveau dans l'\u00e9cole."
},
"information_json": {
"type": "string",
"required": false,
"read_only": false,
"label": "Informations sur l'inscription",
"help_text": "Informations sur l'inscription (bus pour les 2A+, questionnaire pour les 1A), encod\u00e9es en JSON"
},
"user": {
"type": "field",
"required": true,
"read_only": false,
"label": "Utilisateur"
},
"wei": {
"type": "field",
"required": true,
"read_only": false,
"label": "WEI"
}
}
}
}
Filtres Django
~~~~~~~~~~~~~~
* ``user``
* ``user__username``
* ``user__first_name``
* ``user__last_name``
* ``user__email``
* ``user__note__alias__name``
* ``user__note__alias__normalized_name``
* ``wei``
* ``wei__name``
* ``wei__email``
* ``wei__year``
* ``soge_credit``
* ``caution_check``
* ``birth_date``
* ``gender``
* ``clothing_cut``
* ``clothing_size``
* ``first_year``
* ``emergency_contact_name``
* ``emergency_contact_phone``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``user__username`` (expression régulière)
* ``user__first_name`` (expression régulière)
* ``user__last_name`` (expression régulière)
* ``user__email`` (expression régulière)
* ``user__note__alias__name`` (expression régulière)
* ``user__note__alias__normalized_name`` (expression régulière)
* ``wei__name`` (expression régulière)
* ``wei__email`` (expression régulière)
* ``health_issues`` (expression régulière)
* ``emergency_contact_name`` (expression régulière)
* ``emergency_contact_phone`` (expression régulière)
Adhésion au wei
---------------
**Chemin :** `/api/wei/membership/ <https://note.crans.org/api/wei/membership/>`_
Options
~~~~~~~
.. code:: json
{
"name": "Wei Membership List",
"description": "REST API View set.\nThe djangorestframework plugin will get all `BusTeam` objects, serialize it to JSON with the given serializer,\nthen render it on /api/wei/membership/",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "ID"
},
"date_start": {
"type": "date",
"required": false,
"read_only": false,
"label": "L'adh\u00e9sion commence le"
},
"date_end": {
"type": "date",
"required": false,
"read_only": false,
"label": "L'adh\u00e9sion finit le"
},
"fee": {
"type": "integer",
"required": true,
"read_only": false,
"label": "Cotisation",
"min_value": 0,
"max_value": 2147483647
},
"user": {
"type": "field",
"required": true,
"read_only": false,
"label": "Utilisateur"
},
"club": {
"type": "field",
"required": true,
"read_only": false,
"label": "Club"
},
"bus": {
"type": "field",
"required": false,
"read_only": false,
"label": "Bus"
},
"team": {
"type": "field",
"required": false,
"read_only": false,
"label": "\u00c9quipe"
},
"registration": {
"type": "field",
"required": false,
"read_only": false,
"label": "Inscription au WEI"
},
"roles": {
"type": "field",
"required": true,
"read_only": false,
"label": "R\u00f4les"
}
}
}
}
Filtres Django
~~~~~~~~~~~~~~
* ``club__name``
* ``club__email``
* ``club__note__alias__name``
* ``club__note__alias__normalized_name``
* ``user__username``
* ``user__last_name``
* ``user__first_name``
* ``user__email``
* ``user__note__alias__name``
* ``user__note__alias__normalized_name``
* ``date_start``
* ``date_end``
* ``fee``
* ``roles``
* ``bus``
* ``bus__name``
* ``team``
* ``team__name``
* ``registration``
Tris possible
~~~~~~~~~~~~~
* ``id``
* ``date_start``
* ``date_end``
Filtres de recherche
~~~~~~~~~~~~~~~~~~~~
* ``club__name`` (expression régulière)
* ``club__email`` (expression régulière)
* ``club__note__alias__name`` (expression régulière)
* ``club__note__alias__normalized_name`` (expression régulière)
* ``user__username`` (expression régulière)
* ``user__last_name`` (expression régulière)
* ``user__first_name`` (expression régulière)
* ``user__email`` (expression régulière)
* ``user__note__alias__name`` (expression régulière)
* ``user__note__alias__normalized_name`` (expression régulière)
* ``roles__name`` (expression régulière)
* ``bus__name`` (expression régulière)
* ``team__name`` (expression régulière)

110
docs/apps/activity.rst Normal file
View File

@ -0,0 +1,110 @@
Application Activités
=====================
L'application activités gère les différentes activités liées au BDE. Elle permet entre autres de créer des activités qui
peuvent être diffusées via des calendriers ou la mailing list d'événements. Elle permet aussi de réguler l'accès aux
événements, en s'assurant que leur note est positive. Elle permet enfin de gérer les invités.
Modèles
-------
L'application comporte 5 modèles : activités, types d'activité, invités, entrées et transactions d'invitation.
Types d'activité
~~~~~~~~~~~~~~~~
Les activités sont triées par type (pots, soirées de club, ...), et chaque type regroupe diverses informations :
* Nom du type
* Possibilité d'inviter des non-adhérents (booléen)
* Prix d'invitation (entier, centimes à débiter sur la note de l'hôte)
Activités
~~~~~~~~~
Le modèle d'activité regroupe les informations liées à l'activité même :
* Nom de l'activité
* Description de l'activité
* Créateur, personne qui a proposé l'activité
* Club ayant organisé l'activité
* Note sur laquelle verser les crédits d'invitation (peut être nul si non concerné)
* Club invité (généralement le club Kfet)
* Date et heure de début
* Date et heure de fin
* Activité valide (booléen)
* Activité ouverte (booléen)
Entrées
~~~~~~~
Une instance de ce modèle est créé dès que quelqu'un est inscrit à l'activité. Sont stockées les informations suivantes :
* Activité concernée (clé étrangère)
* Heure d'entrée
* Note de la personne entrée, ou hôte s'il s'agit d'un invité (clé étrangère vers ``NoteUser``)
* Invité (``OneToOneField`` vers ``Guest``, ``None`` si c'est la personne elle-même qui rentre et non son invité)
Il n'est pas possible de créer une entrée si la note est en négatif.
Invités
~~~~~~~
Les adhérents ont la possibilité d'inviter des amis. Pour cela, les différentes informations sont enregistrées :
* Activité concernée (clé étrangère)
* Nom de famille
* Prénom
* Note de la personne ayant invité
Certaines contraintes s'appliquent :
* Une personne ne peut pas être invitée plus de 5 fois par an (coupe nom/prénom)
* Un adhérent ne peut pas inviter plus de 3 personnes par activité.
Transactions d'invitation
~~~~~~~~~~~~~~~~~~~~~~~~~
On étend le modèle ``Transaction`` de l'application note afin de supporter les transactions d'invitation. Elles ne
comportent qu'un champ supplémentaire, de type ``OneToOneField`` vers ``Guest``.
Ce modèle aurait pu appartenir à l'application ``note``, mais afin de rester modulaire et que l'application ``note``
ne dépende pas de cette application, on procède de cette manière.
Graphe
~~~~~~
.. image:: /_static/img/graphs/activity.svg
:alt: Graphe de l'application activités
UI
--
Création d'activités
~~~~~~~~~~~~~~~~~~~~
N'importe quel adhérent Kfet peut suggérer l'ajout d'une activité via un formulaire.
Gestion des activités
~~~~~~~~~~~~~~~~~~~~~
Les ayant-droit (Res[pot] et respos infos) peuvent valider les activités proposées. Ils peuvent également la modifier
si besoin. Ils peuvent enfin la déclarer ouvertes pour lancer l'accès aux entrées.
N'importe qui peut inviter des amis non adhérents, tant que les contraintes de nombre (un adhérent n'invite pas plus de
trois personnes par activité et une personne ne peut pas être invitée plus de 5 fois par an). L'invitation est
facturée à l'entrée.
Entrées aux soirées
~~~~~~~~~~~~~~~~~~~
L'interface d'entrées est simple et ergonomique. Elle contient un champ de texte. À chaque fois que le champ est
modifié, un tableau est affiché comprenant la liste des invités et des adhérents dont le prénom, le nom ou un alias
de la note est acceptée par le texte entré.
En cliquant sur la ligne de la personne qui souhaite rentrée, s'il s'agit d'un adhérent, alors la personne est comptée
comme entrée à l'activité, sous réserve que sa note soit positive. S'il s'agit d'un invité, alors 3 boutons
apparaîssent, afin de régler la taxe d'invitation : l'un prélève directement depuis la note de l'hôte, les deux autres
permettent un paiement par espèces ou par carte bancaire. En réalité, les deux derniers boutons enregistrent
automatiquement un crédit sur la note de l'hôte, puis une transaction (de type ``GuestTransaction``) est faite depuis
la note de l'hôte vers la note de l'organisateur de l'événement.

73
docs/apps/index.rst Normal file
View File

@ -0,0 +1,73 @@
Applications de la NoteKfet2020
===============================
.. toctree::
:maxdepth: 2
:caption: Applications
member
note/index
activity
permission
../api/index
registration
logs
treasury
wei
La NoteKfet est un projet Django, décomposé en applications.
Certaines Applications sont développées uniquement pour ce projet, et sont indispensables,
d'autres sont packagesé et sont installées comme dépendances.
Enfin des fonctionnalités annexes ont été rajouté, mais ne sont pas essentiel au déploiement de la NoteKfet;
leur usage est cependant recommandé.
Le front utilise le framework Bootstrap4 et quelques morceaux de javascript custom.
Applications indispensables
---------------------------
* ``note_kfet`` :
Application "projet" de django, c'est ici que la config de la note est gérée.
* `Member <member>`_ :
Gestion des profils d'utilisateurs, des clubs et de leur membres.
* `Note <note>`_ :
Les notes associés a des utilisateurs ou des clubs.
* `Activity <activity>`_ :
La gestion des Activités (créations, gestion, entrée...)
* `Permission <permission>`_ :
Backend de droits, limites les pouvoirs des utilisateurs
* `API <../api>`_ :
API REST de la note, est notamment utilisée pour rendre la note dynamique
(notamment la page de conso)
* `Registration <registration>`_ :
Gestion des inscriptions à la Note Kfet
Applications packagées
----------------------
* ``polymorphic``
Utiliser pour la création de models polymorphiques (``Note`` et ``Transaction`` notamment) cf [Note](Note).
L'utilisation des models polymorphiques est détaillé sur la documentation du package:
`<https://django-polymorphic.readthedocs.io/en/stable/>`_
* ``crispy_forms``
Utiliser pour générer des forms avec bootstrap4
* ``django_tables2``
utiliser pour afficher des tables de données et les formater, en python plutôt qu'en HTML.
* ``restframework``
Base de l'`API <../api>`_.
Applications facultatives
-------------------------
* `Logs <logs>`_
Enregistre toute les modifications effectuées en base de donnée.
* ``cas-server``
Serveur central d'authenfication, permet d'utiliser son compte de la NoteKfet2020 pour se connecter à d'autre application ayant intégrer un client.
* `Script <https://gitlab.crans.org/bde/nk20-scripts>`_
Ensemble de commande `./manage.py` pour la gestion de la note: import de données, verification d'intégrité, etc ...
* `Treasury <treasury>`_ :
Interface de gestion pour les trésoriers, émission de facture, remise de chèque, statistiques ...
* `WEI <wei>`_ :
Interface de gestion du WEI.

50
docs/apps/logs.rst Normal file
View File

@ -0,0 +1,50 @@
Logs
====
Chaque modification effectuée sur un modèle est enregistrée dans la base dans données.
Dès qu'un modèle veut être sauvegardé, deux signaux sont envoyés dans ``logs.signals`` : un avant et un après
la sauvegarde.
En pré-sauvegarde, on récupère l'ancienne version du modèle, si elle existe.
En post-sauvegarde, on récupère l'utilisateur et l'IP courants (voir ci-dessous), on convertit les modèles en JSON
et on enregistre une entrée ``Changelog`` dans la base de données.
Pour récupérer l'utilisateur et son IP, le middleware ``logs.middlewares.LogsMiddlewares`` récupère à chaque requête
l'utilisateur et l'adresse IP, et les stocke dans le processus courant, afin qu'ils puissent être
récupérés par les signaux.
Si jamais la modification ne provient pas d'une requête Web, on suppose qu'elle vient d'une instruction
lancée avec ``manage.py``.
On récupère alors le nom de l'utilisateur dans l'interface de commandes, et si une note est associée à cet alias,
alors on considère que c'est le détenteur de la note qui a effectué cette modification, sur l'adresse IP ``127.0.0.1``.
Sinon, le champ est laissé à ``None``.
Une entrée de ``Changelog`` contient les informations suivantes :
* Utilisateur (``ForeignKey`` vers ``User``, nullable)
* Adresse IP (``GenericIPAddressField``)
* Type de modèle enregistré (``ForeignKey`` vers ``Model``)
* Identifiant ``pk`` de l'instance enregistrée (``CharField``)
* Anciennes données (au format JSON, ``None`` si création de données)
* Nouvelles données (au format JSON, ``None`` si suppression de données)
* Action (``CharField`` avec choix ``create``, ``edit``, ``delete``)
* Date de modification (``DateTimeField``)
Exemple de Changelog, pour la création d'une transaction de 42424242 centimes d'une note vers une autre :
.. code:: json
{
"id": 42,
"ip": "192.168.0.1",
"instance_pk": "1",
"previous": null,
"data": "{\"id\":1,\"created_at\":\"2020-03-11T17:24:09.858651+01:00\",\"quantity\":1,\"amount\":42424242,\"reason\":\"Volons la Kfet\",\"valid\":true,\"polymorphic_ctype\":36,\"source\":6,\"destination\":7}",
"action": "create",
"timestamp": "2020-03-11T17:24:10.088151+01:00",
"user": 1,
"model": 36
}
S'il est préférable de passer en console Postgresql pour parcourir les logs, ils sont trouvables via l'API dans
``/api/logs``, sous réserve d'avoir les droits suffisants (ie. être respo info).

144
docs/apps/member.rst Normal file
View File

@ -0,0 +1,144 @@
Application Member
==================
L'application ``member`` s'occcupe de la gestion des utilisateurs enregistrés.
Le model d'utilisateur ``django.contrib.auth.model.User`` est complété par un ``Profile`` utilisateur.
Tous les utilisateurs peuvent être membre de ``Club``. Cela se traduit par une adhésion ``Membership``, dont les
caractéristiques sont propres à chaque club.
En pratique, la NoteKfet possède au minimum deux Club: **Bde** et **Kfet** (instanciés via les fixtures). Et tous
les personnes à jour de cotisation sont membre à minima de Bde.
Être adhérent du club Kfet permet d'utiliser sa note pour consommer.
Modèles
-------
Utilisateur
~~~~~~~~~~~
Le modèle ``User`` est directement implémenté dans Django et n'appartient pas à l'application ``member``, mais il est
bon de rappeler à quoi ressemble ce modèle.
* ``date_joined`` : ``DateTimeField``, date à laquelle l'utilisateur a été inscrit (*inutilisé dans la Note*)
* ``email`` : ``EmailField``, adresse e-mail de l'utilisateur.
* ``first_name`` : ``CharField``, prénom de l'utilisateur.
* ``is_active`` : ``BooleanField``, indique si le compte est actif et peut se connecter.
* ``is_staff`` : ``BooleanField``, indique si l'utilisateur peut se connecter à l'interface Django-admin.
* ``is_superuser`` : ``BooleanField``, indique si l'utilisateur dispose de droits super-utilisateurs, permettant n'importe quelle action en base de donnée (lecture, ajout, modification, suppression).
* ``last_login`` : ``DateTimeField``, date et heure de dernière connexion.
* ``last_name`` : ``CharField``, nom de famille de l'utilisateur.
* ``password`` : ``CharField``, contient le hash du mot de passe de l'utilisateur. L'algorithme utilisé est celui par défaut de Django : PBKDF2 + HMAC + SHA256 avec 150000 itérations.
* ``username`` : ``CharField`` (unique), pseudo de l'utilisateur.
Profil
~~~~~~
Le modèle ``Profile`` contient un champ ``user`` de type ``OneToOneField``, ce qui permet de voir ce modèle comme une
extension du modèle ``User``, sans avoir à le réécrire. Il contient diverses informations personnelles sur
l'utilisateur, utiles pour l'adhésion au BDE :
* ``user`` : ``OneToOneField(User)``, utilisateur lié à ce profil
* ``address`` : ``CharField``, adresse physique de l'utilisateur
* ``paid`` : ``BooleanField``, indique si l'utilisateur normalien est rémunéré ou non (utile pour différencier les montants d'adhésion aux clubs)
* ``phone_number`` : ``CharField``, numéro de téléphone de l'utilisateur
* ``section`` : ``CharField``, section de l'ENS à laquelle apartient l'utilisateur (exemple : 1A0, ...)
Clubs
~~~~~
La gestion des clubs est une différence majeure avec la Note Kfet 2015. La Note gère ainsi les adhésions des
utilisateurs aux différents clubs.
* ``parent_club`` : ``ForeignKey(Club)``. La présence d'un club parent force l'adhésion au club parent avant de pouvoir adhérer au dit club. Tout club qui n'est pas le club BDE doit avoir le club BDE dans son arborescence.
* ``email`` : ``EmailField``, adresse e-mail sur laquelle contacter le bureau du club.
* ``membership_start`` : ``DateField``, date à partir de laquelle il est possible d'adhérer à un club pour l'année suivante (si adhésions à l'année), en ignorant l'année. Par exemple, l'adhésion BDE est possible à partir du 31/08 par défaut, et c'est à cette date que les adhésions pour l'année future est possible.
* ``membership_end`` : ``DateField``, date maximale de fin d'adhésion. Pour le club BDE, il s'agit du 30/09 de l'année suivante. Si cette valeur vaut ``null``, la fin d'adhésion n'est pas limitée.
* ``membership_duration`` : ``PositiveIntegerField``, durée (en jours) maximale d'adhésion. Par exemple, le club BDE permet des adhésions maximales de 13 mois, soit 396 jours.
* ``membership_fee_paid`` : ``PositiveIntegerField``, montant de la cotisation (en centimes) pour qu'un élève normalien (donc rémunéré) puisse adhérer.
* ``membership_fee_unpaid`` : ``PositiveIntegerField``, montant de la cotisation (en centimes) pour qu'un étudiant normalien (donc non rémunéré) puisse adhérer.
* ``name`` : ``CharField``, nom du club.
* ``require_memberships`` : ``BooleanField``, indique si le club est un vrai club BDE qui nécessite des adhésions de club, ou s'il s'agit d'une note "pot commun" (organisation d'une activité, note de département, ...)
Adhésions
~~~~~~~~~
Comme indiqué précédemment, la note gère les adhésions.
* ``club`` : ``ForeignKey(Club)``, club lié à l'adhésion.
* ``user`` : ``ForeignKey(User)``, utilisateur adhéré.
* ``date_start`` : ``DateField``, date de début d'adhésion.
* ``date_end`` : ``DateField``, date de fin d'adhésion.
* ``fee`` : ``PositiveIntegerField``, montant de la cotisation payée.
* ``roles`` : ``ManyToManyField(Role)``, liste des rôles endossés par l'adhérent.
Rôles
~~~~~
Comme indiqué le modèle des adhésions, les adhésions octroient des rôles aux adhérents, qui offrent des permissions
(cf ``RolesPermissions`` dans la page des permissions). Le modèle ``RolesPermissions`` possède un
``OneToOneField(Role)``, qui implémente les permissions des rôles. Le modèle ``Role`` à proprement parler ne contient
que le champ de son nom (``CharField``).
Transactions d'adhésion
~~~~~~~~~~~~~~~~~~~~~~~
Si le modèle ``MembershipTransaction`` appartient à l'application ``note``, il est bon d'en parler ici.
Le modèle ``MembershipTransaction`` est une extension du modèle ``Transaction`` (application ``note``) qui est de type
polymorphique, et contient en plus des informations de base de la transaction un champ ``OneToOneField(Membership)``
faisant le lien entre l'adhésion et la transaction liée. Une adhésion club, si elle n'est pas gratuite,
génère en effet automatiquement une transaction de l'utilisateur vers le club (voir section adhésions).
Graphe
------
.. image:: /_static/img/graphs/member.svg
:alt: Graphe de l'application member
Adhésions
---------
La Note Kfet offre la possibilité aux clubs de gérer l'adhésion de leurs membres. En plus de réguler les cotisations
des adhérents, des permissions sont octroyées sur la note en fonction des rôles au sein des clubs. Un rôle est une
fonction occupée au sein d'un club (Trésorier de club, président de club, GCKfet, Res[pot], respo info, ...).
Une adhésion attribue à un adhérent ses rôles. Les rôles fournissent les permissions. Par exemple, le trésorier d'un
club a le droit de faire des transferts de et vers la note du club, tant que la source reste au-dessus de -50 €.
Une adhésion est considérée comme valide si la date du jour est comprise (au sens large) entre les dates de début et
de fin d'adhésion.
On peut ajouter une adhésion à un utilisateur dans un club à tout non adhérent de ce club. La personne en charge
d'adhérer quelqu'un choisit l'utilisateur, les rôles au sein du club et la date de début d'adhésion. Cette date de
début d'adhésion doit se situer entre les champs ``club``.``membership_start`` et ``club``.``membership_end``,
si ces champs sont non nuls. Si ``club``.``parent_club`` n'est pas nul, l'utilisateur doit être membre de ce club.
Le montant de la cotisation est fixé en fonction du statut normalien de l'utilisateur (``club``.``membership_fee_paid``
centimes pour les élèves et ``club``.``membership_fee_unpaid`` centimes pour les étudiants). La date de fin est calculée
comme ce qui suit :
* Si ``club``.``membership_duration`` est non nul, alors ``date_end`` = ``date_start`` + ``club.membership_duration``
* Sinon ``club``, ``date_end`` = ``date_start`` + 424242 jours (suffisant pour tenir au moins une vie)
* Si ``club``.``membership_end`` est non nul, alors ``date_end`` = min(``date_end``, ``club``.``membership_end``)
Si l'utilisateur n'est pas membre du club ``Kfet``, l'adhésion n'est pas possible si le solde disponible sur sa note est
insuffisant. Une fois toute ces contraintes vérifiées, l'adhésion est créée. Une transaction de type
``MembershipTransaction`` est automatiquement créée de la note de l'utilisateur vers la note du club, finalisant l'adhésion.
Réadhésions
~~~~~~~~~~~
Pour les clubs nécessitant des adhésions (de durée limitée), il est possible de réadhérer au bout d'un an. Dès lors
que le jour actuel est après ``club``.``membership_start`` + 1 an, ``club``.``membership_start`` et
``club``.membership_end`` sont incrémentés d'un an.
Il est possible de réadhérer si :
* ``membership``.``date_start`` <= ``today`` <= ``membership``.``date_end`` (l'adhésion en cours est valide)
* ``membership``.``date_start`` < ``club``.``membership_start`` (si la date de début d'adhésion du club est postérieure à la date de début d'adhésion, qui a donc été mise à jour, on a changé d'année)
* Il n'y a pas encore de réadhésion (pas d'adhésion au même club vérifiant ``new_membership``.``date_start`` >= ``club``.``membership_start``)
Un bouton ``Réadhérer`` apparaît dans la liste des adhésions si le droit est permis et si ces contraintes sont vérifiées.
En réadhérant, une nouvelle adhésion est créée pour l'utilisateur avec les mêmes rôles, commençant le lendemain de la
date d'expiration de la précédente adhésion. Si on réadhère le 16 août pour une adhésion finissant le 30 septembre,
la nouvelle adhésion commencera le 1er octobre).
Pour supprimer une adhésion (en cas d'erreur), se rendre dans django admin et changer la date de fin d'adhésion,
sans oublier d'invalider la transaction d'adhésion.

View File

@ -0,0 +1,88 @@
Consommations
=============
Affichage
---------
La page de consommations est principalement une communication entre l'`API <../api>`_ et la page en JavaScript.
Elle est disponible à l'adresse ``/note/consos/``, et l'onglet n'est visible que pour ceux ayant le droit de voir au
moins un bouton. L'affichage, comme tout le reste de la page, est géré avec Boostrap 4.
Les boutons que l'utilisateur a le droit de voir sont triés par catégorie.
## Sélection des consommations
Lorsque l'utilisateur commence à taper un nom de note, un appel à l'API sur la page ``/api/note/alias`` est fait,
récupérant les 20 premiers aliases en accord avec la requête. Quand l'utilisateur survole un alias, un appel à la page
``/api/note/note/<NOTE_ID>/`` est fait pour récupérer plus d'infos sur la note telles que le solde, le vrai nom de la
note et la photo, si toutefois l'utilisateur a le droit de voir ceci.
L'utilisateur peut cliquer sur des aliases pour ajouter des émetteurs, et sur des boutons pour ajouter des consommations.
Cliquer dans la liste des émetteurs supprime l'élément sélectionné.
Il ya deux possibilités pour faire consommer des adhérents :
- En mode **consommation simple** (mode par défaut), les consommations sont débitées dès que émetteurs et consommations
sont renseignées.
- En mode **consommation double**, l'utilisateur doit cliquer sur "Consommer !" pour débiter toutes les consommations.
Débit des consommations
-----------------------
Pour débiter toutes les consommations, pour chaque source et chaque bouton, une requête POST est faite à l'API sur
l'adresse ``/api/note/transaction/transaction/`` avec le contenu suivant :
.. code:: json
{
"quantity": "<QUANTITÉ>",
"amount": "<PRIX_EN_CENTIMES>",
"reason": "<NOM_DU_BOUTON> (<CATÉGORIE_DU_BOUTON>)",
"valid": true,
"polymorphic_ctype": 42,
"source": "<ID_DE_NOTE_SOURCE>",
"destination": "<ID_DE_NOTE_DESTINATION>",
"template": "<ID_BOUTON>",
"category": "<ID_CATÉGORIE>",
"resourcetype": "RecurrentTransaction"
}
Par exemple, pour 3 cocas à 1.10 € (catégorie Soft, numéro 1), bouton numéro 1, à destination de la note Kfet (id 6)
depuis la note 7, la requête suivante est envoyée :
.. code:: json
{
"quantity": 3,
"amount": 110,
"reason": "Coca (Soft)",
"valid": true,
"polymorphic_ctype": 42,
"source": 7,
"destination": 6,
"template": 1,
"category": 1,
"resourcetype": "RecurrentTransaction"
}
Le ``42`` dans ``"polymorphic_ctype": 42`` correspond à l'identifiant du modèle `RecurrentTransaction` dans la table
des types. Il vaut `42` lors de la rédaction de cette documentation, mais pourra varier à l'avenir, et sera toujours
à jour : la valeur n'est pas "hard-codée".
Si une erreur survient lors de la requête (droits insuffisants), un message apparaîtra en haut de page.
Dans tous les cas, tous les champs sont réinitialisés.
L'historique et la balance de l'utilisateur sont ensuite mis à jour via jQuery, qui permet de recharger une partie de page Web.
Validation/dévalidation des transactions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Il est possible aussi de (dé)valider une transaction en cliquant sur le symbole de validation. Lorsqu'un clic est fait,
une requête PATCH est faite à l'API sur l'adresse ``/api/note/transaction/transaction/<TRANSACTION_ID>/`` de la forme :
.. code:: json
{
"resourcetype": "RecurrentTransaction",
"valid": false
}
L'historique et la balance sont ensuite rafraîchis. Si une erreur survient, un message apparaîtra.

23
docs/apps/note/index.rst Normal file
View File

@ -0,0 +1,23 @@
Application Note
================
L'application ``note`` gère tout ce qui est en lien avec les flux d'argent et les notes (balances) des utilisateurs.
La gestion des consommations s'effectue principalement via la page dédiée, dont le fonctionnement est expliqué
dans la page `Consommations <consumptions>`_.
Le fonctionnnemnent des crédit/débit de note (avec le "monde extérieur" donc avec de l'argent réel) ainsi que les
transferts/dons entre notes est détaillé sur la page `Transferts <transactions>`_.
.. toctree::
:maxdepth: 2
:caption: Note
consumptions
transfers
Graphe
------
.. image:: /_static/img/graphs/note.svg
:alt: Graphe de l'application note

View File

@ -0,0 +1,34 @@
Transferts
==========
Affichage
---------
L'interface de la page de transferts est semblable à celles des consommations, et l'auto-complétion de note est géré de
la même manière. La page se trouve à l'adresse ``/note/transfer/``. La liste des 20 transactions les plus récentes que
l'utilisateur a le droit de voir est également présente.
Des boutons ``Don``, ``Transfert``, ``Crédit``, ``Retrait`` sont présents, représentant les différents modes de
transfert. Pour chaque transfert, un montant et une description sont attendus.
Onglet transferts
-----------------
Cet onglet est visible par tout le monde. Il permet d'effectuer un transfert depuis plusieurs notes vers d'autres notes,
à l'image des consommations doubles. Si une erreur survient (permission insuffisante), un message d'erreur apparaîtra.
Onglets Crédit et retrait
-------------------------
Ces onglets ne sont visibles que par ceux qui ont le droit de voir les ``SpecialNote``.
Une boîte supplémentaire apparaît, demandant en plus de la note, du montant et de la raison le nom, le prénom et
la banque de la personne à recharger/retirer. Lorsqu'une note est sélectionnée, les champs "nom" et "prénom" sont
remplis automatiquement. Par ailleurs, seule une note peut être choisie.
Transfert
---------
Les transferts se font à nouveau via l'API, avec le même schéma que précédemment, en remplaçant
``RecurrentTransaction`` par ``Transaction`` simplement pour don/transfert, et ``SpecialTransaction`` pour
crédit/retrait, en adaptant le champ ``polymorphic_ctype``.

151
docs/apps/permission.rst Normal file
View File

@ -0,0 +1,151 @@
Droits
======
Le système de droit par défault de django n'est pas suffisament granulaire pour les besoins de la NoteKfet2020.
Un système custom a donc été développé.
Il permet la création de Permission, qui autorise ou non a faire une action précise sur un ou des objets
de la base de données.
Plusieurs permissions peuvent être regroupé dans un Role.
Ce Role est relié a la responsabilité/fonction de la personne dans un Club. Ils sont valable au maximum tant que la
personne est adhérente du Club concerné, mais ce rôle peut être modifié/supprimé avant le terme.
Permission
----------
Une permission est un Model Django dont les principaux attributs sont :
* ``model`` : Le model sur lequel cette permission va s'appliquer
* ``type`` : Les différents types d'interaction sont : voir (``view``), modifier (``change``), ajouter (``add``)
et supprimer (``delete``).
* ``query`` : Requete sur la cible, encodé en JSON, traduit en un Q object (cf [Query](#compilation-de-la-query)
* ``field`` : le champ cible qui pourra etre modifié. (tous les champs si vide)
Pour savoir si un utilisateur a le droit sur un modèle ou non, la requête est compilée (voir ci-dessous) en un filtre
de requête dans la base de données, un objet de la classe ``Q`` (En SQL l'objet Q s'interprete comme tout ce qui suit
un ``WHERE ...`` Ils peuvent être combiné à l'aide d'opérateurs logiques. Plus d'information sur les Q object dans la
`documentation officielle <https://docs.djangoproject.com/fr/2.2/topics/db/queries/#complex-lookups-with-q-objects>`_.
Ce Q object sera donc utilisé pour savoir si l'instance que l'on veux modifier est concernée par notre permission.
Exception faite sur l'ajout d'objets : l'objet n'existant pas encore en base de données, il est ajouté puis supprimé
à la volée, en prenant soin de désactiver les signaux.
Compilation de la query
-----------------------
La query est enregistrée sous un format JSON, puis est traduite en requête ``Q`` récursivement en appliquant certains paramètres.
Le fonctionnemente de base des permission peux être décris avec les differents opérations :
+----------------+-----------------------------+-------------------------------------+
| opérations | JSON | Q object |
+================+=============================+=====================================+
| ALL | ``[]`` ou ``{}`` | ``.objects.get(Q(pk=F("pk"))`` |
+----------------+-----------------------------+-------------------------------------+
| ET | ``["AND", Q_1, Q_2, ... ]`` | ``.objects.get(Q_1 & Q_2 & ...)`` |
+----------------+-----------------------------+-------------------------------------+
| OU | ``["OR", Q_1, Q_2, ...]`` | ``.objects.get(Q_1 \| Q_2 \| ...)`` |
+----------------+-----------------------------+-------------------------------------+
| NON | ``["NOT", Q_1]`` | ``.objects.get(~Q_1)`` |
+----------------+-----------------------------+-------------------------------------+
| key == value | ``{key: value}`` | ``.objects.get(Q(key = value))`` |
+----------------+-----------------------------+-------------------------------------+
Vous n'avez rien compris ? Voilà des exemples :
Exemples
--------
* Permission sur le model ``User`` avec comme query:
.. code:: js
{"is_superuser": true}
| si l'utilisateur cible est un super utilisateur.
* sur le model ``Note`` :
.. code:: js
{"pk":
["user","note", "pk"]
}
| si l'identifiant de la note cible est l'identifiant de l'utilisateur dont on regarde la permission.
* sur le model ``Transaction``:
.. code:: js
["AND",
{"source":
["user", "note"]},
{"amount__lte":
["user", "note", "balance"]}
]
| si la source est la note de l'utilisateur et si le montant est inférieur à son solde.
* Sur le model ``Alias``
.. code:: js
["OR",
{"note__in":
["NoteUser", "objects",[
"filter",{
"user__membership__club__name": "Kfet"
}],
["all"]
]},
{"note__in":
["NoteClub", "objects", ["all"]]
}
]
| si l'alias appartient à une note de club ou s'il appartient à la note d'un utilisateur membre du club Kfet.
* sur le model ``Transaction``
.. code:: js
["AND",
{"destination": ["club", "note"]},
{"amount__lte":
{"F": [
"ADD",
["F", "source__balance"],
5000]
}
}
]
| si la destination est la note du club dont on est membre et si le montant est inférieur au solde de la source + 50 €,
autrement dit le solde final est au-dessus de -50 €.
Masques de permissions
----------------------
Chaque permission est associée à un masque. À la connexion, l'utilisateur choisit le masque de droits avec lequel il
souhaite se connecter. Les masques sont ordonnés totalement, et l'utilisateur aura effectivement une permission s'il est
en droit d'avoir la permission et si son masque est suffisamment haut.
Par exemple, si la permission de voir toutes les transactions est associée au masque "Droits note uniquement",
se connecter avec le masque "Droits basiques" n'octroiera pas cette permission tandis que le masque "Tous mes droits" oui.
Signaux
-------
À chaque fois qu'un modèle est modifié, ajouté ou supprimé, les droits sont contrôlés. Si les droits ne sont pas
suffisants, une erreur est lancée. Pour ce qui est de la modification, on ne contrôle que les champs réellement
modifiés en comparant l'ancienne et la nouvele instance.
Graphe des modèles
------------------
.. image:: /_static/img/graphs/permission.svg
:alt: Graphe de l'application permission

View File

@ -0,0 +1,61 @@
Inscriptions
============
L'inscription a la note se fait via une application dédiée, sans toutefois avoir de modèle en base de données.
Un formulaire d'inscription est disponible sur la page ``/registration/signup``, accessible depuis n'importe qui,
authentifié ou non. Les informations suivantes sont demandées :
* Prénom
* Nom de famille
* Adresse électronique valide
* Mot de passe
* Confirmation du mot de passe
* Numéro de téléphone (optionnel)
* Département d'études
* Promotion, année d'entrée à l'ENS
* Adresse (optionnel)
* Payé (si la personne perçoit un salaire)
Le mot de passe doit vérifier des contraintes de longueur, de complexité et d'éloignement des autres informations
personnelles.
Le compte est ensuite créé, mais est inactif : la personne ne peut pas se connecter. Elle reçoit un mail lui
demandant de vérifier son adresse. Une fois le lien cliqué, l'adresse mail est validée, mais le compte reste
inactif et la connexion impossible.
Pour valider son compte, il faut se rendre à la Kfet et payer les 5 € d'adhésion BDE (ou 40 € si adhésion Kfet en plus,
15 € si on est après le 1er mars), ou bien dire qu'on a ouvert un compte à la Société générale qui paiera alors
l'adhésion. Le BDE pourra alors contrôler les informations du nouveau venu et valider son inscription.
Toutefois, même si l'inscription est validée, l'inscription restera impossible tant que l'adresse e-mail ne sera pas
validée. Le BDE peut mettre à jour l'adresse e-mail si besoin. Dès lors que l'adresse e-mail sera validée,
le compte sera enfin actif.
Pour récapituler : compte actif = adresse e-mail validée + inscription validée par le BDE.
Lors de la validation de l'inscription, le BDE peut (et doit même) faire un crédit initial sur la future note de
l'utilisateur. Il peut spécifier le type de crédit (carte bancaire/espèces/chèque/virement bancaire), le prénom,
le nom et la banque comme un crédit normal. Cependant, il peut aussi cocher une case "Société générale", si le nouveau
membre indique avoir ouvert un compte à la Société générale via le partenariat Société générale - BDE de
l'ÉNS Paris-Saclay. Dans ce cas, tous les champs sont grisés.
Une fois l'inscription validée, détail de ce qu'il se passe :
* Si crédit de la socitété générale, on mémorise que le fait que la personne ait demandé ce crédit (voir
`Trésorerie <treasury>`_ section crédits de la société générale). Nécessairement, le club Kfet doit être rejoint.
* Sinon, on crédite la note du montant demandé par le nouveau membre (avec comme description "Crédit TYPE (Inscription)"
où TYPE est le type de crédit), après avoir vérifié que le crédit est suffisant (on n'ouvre pas une note négative)
* On adhère la personne au BDE, l'adhésion commence aujourd'hui. Il dispose d'un unique rôle : "Adhérent BDE",
lui octroyant un faible nombre de permissions de base, telles que la visualisation de son compte.
* On adhère la personne au club Kfet si cela est demandé, l'adhésion commence aujourd'hui. Il dispose d'un unique rôle :
"Adhérent Kfet", lui octroyant un nombre un peu plus conséquent de permissions basiques, telles que la possibilité de
faire des transactions, d'accéder aux activités, au WEI, ...
* Si le nouveau membre a indiqué avoir ouvert un compte à la société générale, alors les transactions sont invalidées,
la note n'est pas débitée (commence alors à 0 €).
Par ailleurs, le BDE peut supprimer la demande d'inscription sans problème via un bouton dédié. Cette opération
n'est pas réversible.
L'utilisateur a enfin accès a sa note et peut faire des bêtises :)
L'inscription au BDE et à la Kfet est indépendante de l'inscription au WEI. Voir `WEI <wei>`_ pour l'inscription WEI.

221
docs/apps/treasury.rst Normal file
View File

@ -0,0 +1,221 @@
Application Trésorerie
======================
L'application de Trésorerie facilite la vie des trésorier, et sert d'interface de création de facture.
Elle permet également le suivi des remises de chèques reçus par le BDE et des crédits de la Société générale.
Factures
--------
Modèle des factures
~~~~~~~~~~~~~~~~~~~
Il est possible de créer des factures, qui seront enregistrées en base de données. Les différents attributs sont :
* ``id`` : Le numéro de la facture
* ``name`` : Le nom de la personne ou la raison sociale à qui est destinée la facture
* ``address`` : L'adresse de cette personne ou raison sociale
* ``bde`` : Le nom du fichier contenant le logo du BDE sous lequel a été éditée la facture. Ce champ ne peut pas être
modifié depuis la note, et vaut par défaut le logo du BDE en fonction (exemple : ``Saperlistpopette.png``)
* ``date`` : Le jour d'émission de la facture (par défaut le jour même)
* ``object`` : L'objet de la facture, le titre
* ``description`` : La description de la facture
* ``acquitted`` : Indique si la facture a déjà été acquittée ou non.
Les factures contiennent également certaines valeurs hard-codées pour ne pas polluer la base de données, telle que
la raison sociale du BDE, son adresse ainsi que ses coordonnées bancaires.
Produits
~~~~~~~~
À chaque facture est associée plusieurs produits. Pour permettre cela, un modèle ``Product`` a été créé contenant 4 attributs :
* ``invoice`` : ``ForeignKey`` vers la facture associée au produit
* ``designation`` : Désignation du produit
* ``quantity`` : Quantité achetée
* ``amount`` : Prix unitaire (HT) du produit (peut être négatif si jamais il s'agit d'un rabais, d'un solde prépayé, ...)
Pour ajouter des produits à une facture, cela se passe sur le même formulaire d'ajout/de modification de factures.
Pour cela, on utilise un ``FormSet``, qui permet de gérer un nombre arbitraire de formulaires
(chaque produit est un sous-formulaire).
En en-tête, ce code HTML est généré automatiquement :
.. code:: html
<input type="hidden" name="product_set-TOTAL_FORMS" value="<N>" id="id_product_set-TOTAL_FORMS">
<input type="hidden" name="product_set-INITIAL_FORMS" value="<N>" id="id_product_set-INITIAL_FORMS">
<input type="hidden" name="product_set-MIN_NUM_FORMS" value="0" id="id_product_set-MIN_NUM_FORMS">
<input type="hidden" name="product_set-MAX_NUM_FORMS" value="1000" id="id_product_set-MAX_NUM_FORMS">
``<N>`` est le nombre de produits initialement. Cela permet d'indiquer au FormSet combien de formulaires
il y a et combien il faut en gérer. La partie HTML de chaque produit ressemble à ceci :
.. code:: html
<tr class="row-formset">
<td><input type="text" name="product_set-__prefix__-designation" maxlength="255" id="id_product_set-__prefix__-designation"></td>
<td><input type="number" name="product_set-__prefix__-quantity" min="0" id="id_product_set-__prefix__-quantity"> </td>
<td>
<div class="input-group">
<input type="number" name="product_set-__prefix__-amount" step="0.01" id="id_product_set-__prefix__-amount">
<div class="input-group-append">
<span class="input-group-text">€</span>
</div>
</div>
</td>
<input type="hidden" name="product_set-__prefix__-invoice" value="<INVOICE_ID>" id="id_product_set-__prefix__-invoice">
<input type="hidden" name="product_set-__prefix__-id" id="id_product_set-__prefix__-id">
</tr>
``__prefix__`` est remplacé par le numéro de ligne et ``<INVOICE_ID>`` l'identifiant de la facture
(non renseigné si non encore créé). De cette manière, le FormSet sait associer chaque formulaire à ses données.
On note la présence de deux champs cachés :
* ``product_set-__prefix__-invoice`` contient l'identifiant de la facture (si existant)
* ``product_set-__prefix__-id`` contient l'identifiant du produit en base de données (si existant, sinon 0)
Deux boutons sont présents sur la page, pour ajouter et supprimer un produit. Cela a pour effet de mettre à jour
les informations présentes dans les méta-données du formulaire présentées ci-dessus, et de copier une ligne vide
(présentée ci-dessus) et de l'afficher en remplaçant ``__prefix__`` par les bonnes valeurs.
Au moment de la sauvegarde du formulaire, on s'assure d'enregistrer tous les produits associés.
Génération
~~~~~~~~~~
Les factures peuvent s'exporter au format PDF (là est tout leur intérêt). Pour cela, on utilise le template LaTeX
présent à l'adresse suivante :
`/templates/treasury/invoice_sample.tex <https://gitlab.crans.org/bde/nk20/-/tree/master/templates/treasury/invoice_sample.tex>`_
On le remplit avec les données de la facture et les données du BDE, hard-codées. On copie le template rempli dans un
ficher tex dans un dossier temporaire. On fait ensuite 2 appels à ``pdflatex`` pour générer la facture au format PDF.
Les deux appels sont nécessaires, il y a besoin d'un double rendu. Ensuite, le PDF est envoyé à l'utilisateur et on
supprime les données temporaires.
On remarque que les PDF sont générés à la volée et ne sont pas sauvegardés. Niveau performances, cela prend du temps
au plus 2-3 secondes), mais cela n'est pas un problème car on ne génère pas des factures fréquemment. Niveau fiabilité
des données, il faut s'assurer que les données hard-codées ne changent pas, et si elles sont amenées à changer
(pour cause de déménagement), il faudra s'assurer que cela n'impacte pas les anciennes factures, en ajoutant par
exemple un champ ``old`` (ou ``kchan``) pour savoir s'il s'agit d'une nouvelle ou d'une ancienne facture.
Remises de chèques
------------------
L'application trésorerie permet aussi de gérer les remises de chèques. En réalité, elle permet de gérer également des
remises de crédit par carte bancaire, virement ou espèces, mais cela n'étant pas utilisé, ces types de transactions
aparaîtront comme non supportées.
Différents modèles
~~~~~~~~~~~~~~~~~~
Types de remises
^^^^^^^^^^^^^^^^
Comme indiqué ci-dessus, tous les types de remises ne sont pas supportés. Pour cela, on passe par un modèle
``RemittanceType`` qui contient uniquement un champ ``OneToOneField`` vers un objet ``NoteSpecial``.
On peut alors voir ``RemittanceType`` comme un sous-ensemble des notes spéciales, qui correspond aux types de remises
supportées. Par défaut, seule la note ``Chèque`` est supportée (après chargement des données initiales).
L'intérêt de ce genre de procédé plutôt que d'ajouter un booléen dans le modèle ``NoteSpecial`` est d'empêcher toute
dépendance de l'application ``treasury`` dans l'application ``note``, la rendant plus externe.
Proxys vers transactions de crédit
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
De la même manière que les types de remise, ce modèle, appelé ``SpecialTransactionProxy``, n'existe que pour rendre
l'application ``treasury`` externe et de ne pas surcharger le modèle ``SpecialTransaction``.
Ce modèle contient deux attributs :
* ``transaction`` : ``OneToOneField`` vers ``SpecialTransaction``
* ``remittance`` : ``ForeignKey`` vers ``Remittance`` (voir ci-dessous), remise associée à cette transaction
À chaque fois qu'une transaction spéciale d'un type accepté est créée, un proxy est ajouté automatiquement par le biais
d'un signal. De plus, à chaque fois que le serveur web démarre, les vieilles transactions d'un bon type sans proxy s'en
voient dotées d'un.
Remises
^^^^^^^
Les modèles des remises contiennent les attributs suivants :
* ``remittance_type`` : ``ForeignKey`` vers ``RemittanceType`` : type de remise (chèque, carte bancaire, virement, espèces)
* ``date`` : date et heure d'ouverture de la remise (``DateTimeField``)
* ``comment`` : commentaire sur la remise, description
* ``closed`` : booléen indiquant si la remise est close ou non
Ce modèle contient des propriétés supplémentaires :
* ``transactions`` : ``QuerySet<SpecialTransaction>``, transactions liées à la remise
* ``count`` : nombre de transactions liées
* ``amount`` : somme totale des transactions liées
Relations
~~~~~~~~~
* Toute transaction qui n'est pas attachée à une remise d'un bon type peut être attachée à une remise. Cela se passe
par le biais d'un formulaire, où le trésorier peut vérifier et corriger au besoin nom, prénom, banque émettrice et montant.
* Toute transaction attachée à une remise encore ouverte peut être retirée.
* Pour clore une remise, il faut au moins 1 transaction associée.
* Il n'est plus possible de modifier de quelque manière que ce soit une remise close, que ce soit en modifiant le
commentaire, en ajoutant ou en supprimant une transaction attachée.
* Il n'est pas possible de modifier le type d'une remise. De plus, il n'est pas possible d'ajouter une transaction à
une remise si elle n'est pas du bon type.
Crédits de la Société générale
------------------------------
La note permet la gestion des crédits de la Société générale, conformément au partenariat établi entre la banque et le BDE.
Modèle
~~~~~~
Cette sous-application dispose d'un unique modèle "SogeCredit" avec les champs suivant :
* ``user`` : ``OneToOneField`` vers ``User``, utilisateur associé à ce crédit (relation ``OneToOne`` car chaque
utilisateur ne peut bénéficier qu'une seule fois d'un crédit de la Société générale)
* ``transactions`` : ``ManyToManyField`` vers ``MembershipTransaction``, liste des transactions d'adhésion associées
à ce crédit, généralement adhésion BDE+Kfet+WEI même si cela n'est pas restreint
* ``credit_transaction`` : ``OneToOneField`` vers ``SpecialTransaction``, peut être nulle, transaction de crédit de la
Société générale vers la note de l'utilisateur si celui-ci a été validé. C'est d'ailleurs le témoin
de validation du crédit.
On sait qu'un utilisateur a déjà demandé un crédit de la Société générale s'il existe un crédit associé à cet
utilisateur avec une transaction associée. Par ailleurs, le modèle ``Profile`` contient une propriété ``soge`` qui
traduit exactement ceci, et qui vaut ``False`` si jamais l'application Trésorerie n'est pas chargée.
Si jamais l'utilisateur n'a pas encore demandé de crédit de la Société générale (ou que celui-ci n'est pas encore validé),
l'utilisateur peut demander un tel crédit lors de son adhésion BDE, de sa réadhésion BDE ou de son inscription au WEI.
Dans les deux premiers cas, il est invité à jumeler avec une nouvelle adhésion Kfet (merci de d'abord se réadhérer au
BDE avant la Kfet dans ce cas).
Lorsqu'une telle demande est faite, l'adhésion est créée avec une transaction d'adhésion invalide. Cela implique que
la note source n'est pas débitée et la note destination n'est pas créditée.
Sur son interface, le trésorier peut récupérer les crédits de Société générale invalides. Deux options s'offrent à lui :
* Supprimer la demande. Dans ce cas, les transactions vont être validées, la note de l'utilisateur sera débité, les
clubs seront crédités. Puisque la demande sera supprimée, l'utilisateur pourra à nouveau à l'avenir déclarer avoir
ouvert un compte à la Société générale. Cette option est utile dans le cas où l'utilisateur est un boulet (ou pas,
pour d'autres raisons) et a déclaré vouloir ouvrir un compte à la Société générale sans ne rien faire.
Cette action est irréversible, et n'est pas possible si la note de l'utilisateur n'a pas un solde suffisant.
* Valider la demande. Dans ce cas, un crédit de la note "Virements bancaires" vers la note de l'utilisateur sera créé,
la transaction sera liée à la demande via le champ ``credit_note`` (et donc la demande déclarée valide), et toutes les
transactions d'adhésion seront déclarées valides.
* Demander à un respo info s'il y a un problème pour le régler avant de faire des bêtises. Je l'admets, ça fait trois options.
La validité d'une transaction d'adhésion n'a aucune influence sur l'adhésion elle-même. Toutefois, cela se remarque rapidement ...
.. image:: /_static/img/treasury_validate_sogecredit.png
Exemple de validation de crédit Société générale d'un étudiant non payé "toto2" s'étant inscrit au BDE, à la Kfet et au WEI.
Diagramme des modèles
---------------------
.. image:: /_static/img/graphs/treasury.svg
:alt: Graphe de l'application trésorerie

332
docs/apps/wei.rst Normal file
View File

@ -0,0 +1,332 @@
WEI
===
Cette application gère toute la phase d'inscription au WEI.
Modèles
-------
WEIClub
~~~~~~~
Le modèle ``WEIClub`` hérite de ``Club`` et contient toutes les informations d'un WEI.
* ``year`` : ``PositiveIntegerField`` unique, année du WEI.
* ``date_start`` : ``DateField``, date de début du WEI.
* ``date_end`` : ``DateField``, date de fin du WEI.
Champs hérités de ``Club`` de l'application ``member`` :
* ``parent_club`` : ``ForeignKey(Club)``. Ce champ vaut toujours ``Kfet`` dans le cas d'un WEI : on doit être membre du
club Kfet pour participer au WEI.
* ``email`` : ``EmailField``, adresse e-mail sur laquelle contacter les gérants du WEI.
* ``membership_start`` : ``DateField``, date à partir de laquelle il est possible de s'inscrire au WEI.
* ``membership_end`` : ``DateField``, date de fin d'adhésion possible au WEI.
* ``membership_duration`` : ``PositiveIntegerField``, inutilisé dans le cas d'un WEI, vaut ``None``.
* ``membership_fee_paid`` : ``PositiveIntegerField``, montant de la cotisation (en centimes) pour qu'un élève normalien
(donc rémunéré) puisse adhérer.
* ``membership_fee_unpaid`` : ``PositiveIntegerField``, montant de la cotisation (en centimes) pour qu'un étudiant
normalien (donc non rémunéré) puisse adhérer.
* ``name`` : ``CharField``, nom du WEI.
* ``require_memberships`` : ``BooleanField``, vaut toujours ``True`` pour le WEI.
Bus
~~~
Contient les informations sur un bus allant au WEI.
* ``wei`` : ``ForeignKey(WEIClub)``, WEI auquel ce bus est rattaché.
* ``name`` : ``CharField``, nom du bus. Le champ est unique pour le WEI attaché.
* ``description`` : ``TextField``, description textuelle de l'ambiance du bus.
* ``information_json`` : ``TextField``, diverses informations non publiques qui permettent d'indiquer divers paramètres
pouvant varier selon les années permettant l'attribution des bus aux 1A.
Il est souhaitable de créer chaque année un bus "Staff" (non accessible aux 1A bien évidemment) pour les GC WEI qui ne
monteraient pas dans un bus.
BusTeam
~~~~~~~
Contient les informations d'une équipe WEI.
* ``wei`` : ``ForeignKey(WEIClub)``, WEI auquel cette équipe est rattachée.
* ``name`` : ``CharField``, nom de l'équipe.
* ``color`` : ``PositiveIntegerField``, entier entre 0 et 16777215 = 0xFFFFFF représentant la couleur du T-Shirt.
La donnée se rentre en hexadécimal via un sélecteur de couleur. Cette information est purement cosmétique et n'est
utilisée nulle part.
* ``description`` : ``TextField``, description de l'équipe.
WEIRole
~~~~~~~
Ce modèle hérité de ``Role``, ne contient qu'un champ ``name`` (``CharField``), le nom du rôle. Ce modèle ne permet
que de dissocier les rôles propres au WEI des rôles s'appliquant pour n'importe quel club.
WEIRegistration
~~~~~~~~~~~~~~~
Inscription au WEI, contenant les informations avant validation. Ce modèle est créé dès lors que quelqu'un se pré-inscrit au WEI.
* ``user`` : ``ForeignKey(User)``, utilisateur qui s'est pré-inscrit. Ce champ est unique avec ``wei``.
* ``wei`` : ``ForeignKey(WEIClub)``, le WEI auquel l'utilisateur s'est pré-inscrit. Ce champ est unique avec ``user``.
* ``soge_credit`` : ``BooleanField``, indique si l'utilisateur a déclaré vouloir ouvrir un compte à la Société générale.
* ``caution_check`` : ``BooleanField``, indique si l'utilisateur (en 2ème année ou plus) a bien remis son chèque de
caution auprès de la trésorerie.
* ``birth_date`` : ``DateField``, date de naissance de l'utilisateur.
* ``gender`` : ``CharField`` parmi ``male`` (Homme), ``female`` (Femme), ``non binary`` (Non binaire), genre de la personne.
* ``health_issues`` : ``TextField``, problèmes de santé déclarés par l'utilisateur.
* ``emergency_contact_name`` : ``CharField``, nom du contact en cas d'urgence.
* ``emergency_contact_phone`` : ``CharField``, numéro de téléphone du contact en cas d'urgence.
* ``ml_events_registration`` : ``BooleanField``, déclare si l'utilisateur veut s'inscrire à la liste de diffusion des
événements du BDE (1A uniquement)
* ``ml_art_registration`` : ``BooleanField``, déclare si l'utilisateur veut s'inscrire à la liste de diffusion des
actualités du BDA (1A uniquement)
* ``ml_sport_registration`` : ``BooleanField``, déclare si l'utilisateur veut s'inscrire à la liste de diffusion des
actualités du BDS (1A uniquement)
* ``first_year`` : ``BooleanField``, indique si l'inscription est d'un 1A ou non. Non modifiable par n'importe qui.
* ``information_json`` : ``TextField`` non modifiable manuellement par n'importe qui stockant les informations du
questionnaire d'inscription au WEI pour les 1A, et stocke les demandes faites par un 2A+ concerant bus, équipes et rôles.
On utilise un ``TextField`` contenant des données au format JSON pour permettre de la modularité au fil des années,
sans avoir à tout casser à chaque fois.
WEIMembership
~~~~~~~~~~~~~
Ce modèle hérite de ``Membership`` et contient les informations d'une adhésion au WEI.
* ``bus`` : ``ForeignKey(Bus)``, bus dans lequel se trouve l'utilisateur.
* ``team`` : ``ForeignKey(BusTeam)`` pouvant être nulle (pour les chefs de bus et électrons libres), équipe dans laquelle
se trouve l'utilisateur.
* ``registration`` : ``OneToOneField(WEIRegistration)``, informations de la pré-inscription.
Champs hérités du modèle ``Membership`` :
* ``club`` : ``ForeignKey(Club)``, club lié à l'adhésion. Doit être un ``WEIClub``.
* ``user`` : ``ForeignKey(User)``, utilisateur adhéré.
* ``date_start`` : ``DateField``, date de début d'adhésion.
* ``date_end`` : ``DateField``, date de fin d'adhésion.
* ``fee`` : ``PositiveIntegerField``, montant de la cotisation payée.
* ``roles`` : ``ManyToManyField(Role)``, liste des rôles endossés par l'adhérent. Les rôles doivent être des ``WEIRole``.
Graphe des modèles
~~~~~~~~~~~~~~~~~~
Pour une meilleure compréhension, le graphe des modèles de l'application ``member`` ont été ajoutés au schéma.
.. image:: /_static/img/graphs/wei.svg
:alt: Graphe des modèles de l'application WEI
Fonctionnement
--------------
Création d'un WEI
~~~~~~~~~~~~~~~~~
Seul un respo info peut créer un WEI. Pour cela, se rendre dans l'onglet WEI, puis "Liste des WEI" et enfin
"Créer un WEI". Diverses informations sont demandées, comme le nom du WEI, l'adresse mail de contact, l'année du WEI
(doit être unique), les dates de début et de fin, et les dates pendant lesquelles les utilisateurs peuvent s'inscrire.
Don des droits à un GC WEI
~~~~~~~~~~~~~~~~~~~~~~~~~~
Le GC WEI peut gérer tout ce qui a un rapport avec le WEI. Il ne peut cependant pas créer le WEI, ce privilège est
réservé au respo info. Pour avoir ses droits, le GC WEI doit s'inscrire au WEI avec le rôle GC WEI, et donc payer
en premier sa cotisation. C'est donc au respo info de créer l'adhésion du GC WEI. Voir ci-dessous pour l'inscription au WEI.
S'inscrire au WEI
~~~~~~~~~~~~~~~~~
N'importe quel utilisateur peut s'auto-inscrire au WEI, lorsque les dates d'adhésion le permettent. Ceux qui se sont
déjà inscrits peuvent également inscrire un 1A. Seuls les GC WEI et les respo info peuvent inscrire un autre 2A+.
À tout moment, tant que le WEI n'est pas passé, l'inscription peut être modifiée, même après validation.
Inscription d'un 2A+
^^^^^^^^^^^^^^^^^^^^
Comme indiqué, les 2A+ sont assez autonomes dans leur inscription au WEI. Ils remplissent le questionnaire et sont
ensuite pré-inscrits. Le questionnaire se compose de plusieurs champs (voir WEIRegistration) :
* Est-ce que l'utilisateur a déclaré avoir ouvert un compte à la Société générale ? (Option disponible uniquemement
si cela n'a pas été fait une année avant)
* Date de naissance
* Genre (Homme/Femme/Non-binaire)
* Problèmes de santé
* Nom du contact en cas d'urgence
* Numéro du contact en cas d'urgence
* Bus préférés (choix multiple, utile pour les électrons libres)
* Équipes préférées (choix multiple éventuellement vide, vide pour les chefs de bus/staff)
* Rôles souhaités
Les trois derniers champs n'ont aucun caractère définitif et sont simplement là en suggestion pour le GC WEI qui
validera l'inscription. C'est utile si on hésite entre plusieurs bus.
L'inscription est ensuite créée, le GC WEI devra ensuite la valider (voir plus bas).
Inscription d'un 1A
^^^^^^^^^^^^^^^^^^^
N'importe quelle personne déjà inscrite au WEI peut inscrire un 1A. Le formulaire 1A est assez peu différent du formulaire 2A+ :
* Est-ce que l'utilisateur a déclaré avoir ouvert un compte à la Société générale ?
* Date de naissance
* Genre (Homme/Femme/Non-binaire)
* Problèmes de santé
* Nom du contact en cas d'urgence
* Numéro du contact en cas d'urgence
* S'inscrire à la ML événements
* S'inscrire à la ML BDA
* S'inscrire à la ML BDS
Le 1A ne peut donc pas choisir de son bus et de son équipe, et peut s'inscrire aux listes de diffusion.
Il y a néanmoins une différence majeure : une fois le formulaire rempli, un questionnaire se lance.
Ce questionnaire peut varier au fil des années (voir section Questionnaire), et contient divers formulaires de collecte
de données qui serviront à déterminer quel est le meilleur bus pour ce nouvel utilisateur.
Questionnaire 1A
^^^^^^^^^^^^^^^^
Le questionnaire 1A permet de poser des questions aux 1A lors de leur inscription au WEI afin de déterminer quel serait
le meilleur bus pour eux. Un algorithme attribue ensuite à chaque 1A le bus sélectionné.
Afin de permettre de la modularité et de s'adapter aux changements au fil des années, il n'y a pas de modèle dédié au
sondage. On sauvegarde alors les données du sondage sous la forme d'un dictionnaire enregistré au format JSON
dans le champ ``information_json`` du modèle ``WEIRegistration``. Ce champ est modifiable manuellement uniquement par
les respos info et les GC WEI.
Je veux changer d'algorithme de répartition, que faire ?
""""""""""""""""""""""""""""""""""""""""""""""""""""""""
Cette section est plus technique et s'adresse surtout aux respos info en cours de mandat.
Première règle : on ne supprime rien (sauf si vraiment c'est du mauvais boulot). En prenant exemple sur des fichiers déjà existant tels que ``apps/wei/forms/surveys/wei2020.py``, créer un nouveau fichier ``apps/wei/forms/surveys/wei20XY.py``. Ce fichier doit inclure les éléments suivants :
WEISurvey
"""""""""
Une classe héritant de ``wei.forms.surveys.base.WEISurvey``, comportant les éléments suivants :
* Une fonction ``get_year(cls)`` indiquant l'année du WEI liée au sondage
* Une fonction ``get_survey_information_class(cls)`` indiquant la classe héritant de
``wei.forms.surveys.base.WEISurveyInformation`` contenant les données du sondage (voir plus bas)
* Une fonction ``get_algorithm_class(cls)`` indiquant la classe héritant de
``wei.forms.surveys.base.WEISurveyAlgorithm`` contenant l'algorithme de répartition (voir plus bas)
* Une fonction ``get_form_class(self)`` qui indique la classe du formulaire Django à remplir. Cette classe peut dépendre
de l'état actuel du sondage.
* Une fonction ``update_form(self, form)``, optionnelle, appelée lorsqu'un formulaire dont la classe est spécifiée via
la fonction ``get_form_class``, et permet d'opérer sur le formulaire si besoin.
* Une fonction ``form_valid(self, form)`` qui indique quoi faire lorsque le formulaire est rempli. Cette fonction peut
bien sûr dépendre de l'état actuel du sondage.
* Une fonction ``is_complete(self)`` devant renvoyer un booléen indiquant si le sondage est complet ou non.
Naturellement, il est implicite qu'une fonction ayant pour premier argument ``cls`` doit être annotée par ``@classmethod``.
Nativement, la classe ``WEISurvey`` comprend les informations suivantes :
* ``registration``, le modèle ``WEIRegistration`` de l'utilisateur qui remplit le questionnaire
* ``information``, instance de ``WEISurveyInformation``, contient les données du questionnaire en cours de remplissage.
* ``get_wei(cls)``, renvoie le WEI correspondant à l'année du sondage.
* ``save(self)``, enregistre les informations du sondage dans l'objet ``registration`` associé, qui est ensuite
enregistré en base de données.
* ``select_bus(self, bus)``, choisit le bus ``bus`` comme bus préféré. Cela à pour effet de remplir les champs
``selected_bus_pk`` et ``selected_bus_name`` par les identifiant et nom du bus, et ``valid`` à ``True``.
Pour information, ``WEISurvey.__init__`` prend comme paramètre l'inscription ``registration``, et récupère les
informations du sondage converties en dictionnaire Python puis en objet ``WEISurveyInformation``.
WEISurveyInformation
""""""""""""""""""""
Une classe héritant de ``wei.forms.surveys.base.WEISurveyInformation``, comportant les informations brutes du sondage.
Le champ ``information_json`` de ``WEIRegistration`` est traduit en dictionnaire Python depuis JSON, puis les différents
champs de WEISurveyInformation sont mis à jour depuis ce dictionnaire. Il n'y a rien de supplémentaire à ajouter, tout
est déjà géré.
Ainsi, plutôt que de modifier laborieusement le champ JSON, préférez utiliser cette classe. Attention : pour des soucis
de traduction facile, merci de n'utiliser que des objets primitifs (nombres, chaînes de caractère, booléens, listes,
dictionnaires simples). Les instances de modèle sont à proscrire, préférez stocker l'identifiant et créer une fonction
qui récupère l'instance à partir de l'identifiant.
Attention, 3 noms sont réservés : ``selected_bus_pk``, ``selected_bus_name`` et ``valid``, qui représentent la sortie
de l'algorithme de répartition.
À noter que l'interface de validation des inscriptions affiche les données brutes du sondage.
WEIBusInformation
"""""""""""""""""
Une classe héritant de ``wei.forms.surveys.base.WEIBusInformation``, qui contient les informations sur un bus,
de la même manière que ``WEISurveyInformation`` contient les informations d'un sondage. Le fonctionnement est le même :
on récupère le champ ``information_json`` du modèle ``Bus`` qu'on convertit en dictionnaire puis en objet Python.
Cet objet est en lecture uniquement, on modifie à la main les paramètres d'un bus.
Le champ ``bus`` est fourni.
WEISurveyAlgorithm
""""""""""""""""""
Une classe héritant de ``wei.forms.surveys.base.WEISurveyAlgorithm``, qui contient 3 fonctions :
* ``get_survey_class(cls)``, qui renvoie la classe du ``WEISurvey`` associée à l'algorithme.
* ``get_bus_information_class(cls)`` qui renvoie la classe du ``WEIBusInformation`` décrivant les informations d'
* ``run_algorithm(self)``, la fonction importante. Cette fonction n'est supposée n'être exécutée qu'une seule fois
par WEI, et a pour cahier des charges de prendre chaque sondage d'un 1A et d'appeler la fonction ``WEISurvey.select_bus(bus)``,
en décidant convenablement de quel bus le membre doit prendre. C'est bien sûr la fonction la plus complexe à mettre en oeuvre.
Tout est permis tant qu'à la fin tout le monde a bien son bus.
Trois fonctions sont implémentées nativement :
* ``get_registrations(cls)``, renvoie un ``QuerySSet`` vers l'ensemble des inscriptions au WEI concerné des 1A.
* ``get_buses(cls)``, renvoie l'ensemble des bus du WEI concerné.
* ``get_bus_information(cls, bus)``, renvoie l'objet ``WEIBusInformation`` instancié avec les informations fournies
par le champ ``information_json`` de ``bus``.
La dernière chose à faire est dans le fichier ``apps/wei/forms/surveys/__init__.py``, où la classe ``CurrentSurvey``
est à mettre à jour. Il n'y a rien d'autre à changer, tout le reste est normalement géré pour qu'il n'y ait pas nécessité
d'y toucher.
Le lancement de l'algorithme se fait en ligne de commande, via la commande ``python manage.py wei_algorithm``. Elle a
pour unique effet d'appeler la fonction ``run_algorithm`` décrite plus tôt. Une fois cela fait, vous aurez noté qu'il
n'a pas été évoqué d'adhésion. L'adhésion est ensuite manuelle, l'algorithme ne fournit qu'une suggestion.
Cette structure, complexe mais raisonnable, permet de gérer plus ou moins proprement la répartition des 1A,
en limitant très fortement le hard code. Ami nouveau développeur, merci de bien penser à la propreté du code :)
En particulier, on évitera de mentionner dans le code le nom des bus, et profiter du champ ``information_json``
présent dans le modèle ``Bus``.
Valider les inscriptions
~~~~~~~~~~~~~~~~~~~~~~~~
Cette partie est moins technique.
Une fois la pré-inscription faite, elle doit être validée par le BDE, afin de procéder au paiement. Le GC WEI a accès à
la liste des inscriptions non validées, soit sur la page de détails du WEI, soit sur un tableau plus large avec filtre.
Une inscription non validée peut soit être validée, soit supprimée (la suppression est irréversible).
Lorsque le GC WEI veut valider une inscription, il a accès au récapitulatif de l'inscription ainsi qu'aux informations
personnelles de l'utilisateur. Il lui est proposé de les modifier si besoin (du moins les informations liées au WEI,
pas les informations personnelles). Il a enfin accès aux résultats du sondage et la sortie de l'algorithme s'il s'agit
d'un 1A, aux préférences d'un 2A+. Avant de valider, le GC WEI doit sélectionner un bus, éventuellement une équipe
et un rôle. Si c'est un 1A et que l'algorithme a tourné, ou si c'est un 2A+ qui n'a fait qu'un seul choix de bus,
d'équipe, de rôles, les champs sont automatiquement pré-remplis.
Quelques restrictions cependant :
* Si c'est un 2A+, le chèque de caution doit être déclaré déposé
* Si l'inscription se fait via la Société générale, un message expliquant la situation apparaît : la transaction de
paiement sera créée mais invalidée, les trésoriers devront confirmer plus tard sur leur interface que le compte
à la Société générale a bien été créé avant de valider la transaction (voir `Trésorerie <treasury>`_ section
Crédit de la Société générale).
* Dans le cas contraire, l'utilisateur doit avoir le solde nécessaire sur sa note avant de pouvoir adhérer.
* L'utilisateur doit enfin être membre du club Kfet. Un lien est présent pour le faire adhérer ou réadhérer selon le cas.
Si tout est bon, le GC WEI peut valider. L'utilisateur a bien payé son WEI, et son interface est un peu plus grande.
Il peut toujours changer ses paramètres au besoin. Un 1A ne voit rien de plus avant la fin du WEI.
Un adhérent WEI non 1A a accès à la liste des bus, des équipes et de leur descriptions. Les chefs de bus peuvent gérer
les bus et leurs équipes. Les chefs d'équipe peuvent gérer leurs équipes. Cela inclut avoir accès à la liste des membres
de ce bus / de cette équipe.
Un export au format PDF de la liste des membres *visibles* est disponible pour chacun.
Bon WEI à tous !

63
docs/conf.py Normal file
View File

@ -0,0 +1,63 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
# -- Project information -----------------------------------------------------
project = 'Note Kfet 2020'
copyright = '2020, BDE ENS Paris-Saclay'
author = 'BDE ENS Paris-Saclay'
# The full version, including alpha/beta/rc tags
release = '1.0.1'
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
"sphinx_rtd_theme",
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = 'fr'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']

14
docs/index.rst Normal file
View File

@ -0,0 +1,14 @@
Documentation de la Note Kfet 2020
==================================
Bienvenue sur le Wiki de la NoteKfet2020. Ce wiki est plutot orienté vers un public de développeur, qui souhaitent
contribuer au développement, mais expliquent également aux plus curieux comment fonctionne la NoteKfet2020 sous le capot.
Des informations complémentaires sont également disponibles sur le `Wiki Crans <https://wiki.crans.org/NoteKfet/NoteKfet2020/>`_.
.. toctree::
:maxdepth: 2
:caption: Développement de la NK20
apps/index

2
docs/requirements.txt Normal file
View File

@ -0,0 +1,2 @@
sphinx~=3.3
sphinx-rtd-theme~=0.5

View File

@ -16,6 +16,9 @@ server {
location /media {
alias /var/www/note_kfet/media;
}
location /doc {
alias /var/www/documentation;
}
# Send all non-media requests to the Django server.
location / {

View File

@ -49,6 +49,7 @@ INSTALLED_APPS = [
'django.contrib.staticfiles',
'django.forms',
'django_filters',
'django_extensions',
# API
'rest_framework',