Hugo Levy-Falk
3 years ago
commit
f3df8d70e1
5 changed files with 666 additions and 0 deletions
@ -0,0 +1,302 @@ |
|||
|
|||
# Created by https://www.toptal.com/developers/gitignore/api/latex |
|||
# Edit at https://www.toptal.com/developers/gitignore?templates=latex |
|||
|
|||
### LaTeX ### |
|||
## Core latex/pdflatex auxiliary files: |
|||
*.aux |
|||
*.lof |
|||
*.log |
|||
*.lot |
|||
*.fls |
|||
*.out |
|||
*.toc |
|||
*.fmt |
|||
*.fot |
|||
*.cb |
|||
*.cb2 |
|||
.*.lb |
|||
|
|||
## Intermediate documents: |
|||
*.dvi |
|||
*.xdv |
|||
*-converted-to.* |
|||
# these rules might exclude image files for figures etc. |
|||
# *.ps |
|||
# *.eps |
|||
# *.pdf |
|||
|
|||
## Generated if empty string is given at "Please type another file name for output:" |
|||
.pdf |
|||
|
|||
## Bibliography auxiliary files (bibtex/biblatex/biber): |
|||
*.bbl |
|||
*.bcf |
|||
*.blg |
|||
*-blx.aux |
|||
*-blx.bib |
|||
*.run.xml |
|||
|
|||
## Build tool auxiliary files: |
|||
*.fdb_latexmk |
|||
*.synctex |
|||
*.synctex(busy) |
|||
*.synctex.gz |
|||
*.synctex.gz(busy) |
|||
*.pdfsync |
|||
|
|||
## Build tool directories for auxiliary files |
|||
# latexrun |
|||
latex.out/ |
|||
|
|||
## Auxiliary and intermediate files from other packages: |
|||
# algorithms |
|||
*.alg |
|||
*.loa |
|||
|
|||
# achemso |
|||
acs-*.bib |
|||
|
|||
# amsthm |
|||
*.thm |
|||
|
|||
# beamer |
|||
*.nav |
|||
*.pre |
|||
*.snm |
|||
*.vrb |
|||
|
|||
# changes |
|||
*.soc |
|||
|
|||
# comment |
|||
*.cut |
|||
|
|||
# cprotect |
|||
*.cpt |
|||
|
|||
# elsarticle (documentclass of Elsevier journals) |
|||
*.spl |
|||
|
|||
# endnotes |
|||
*.ent |
|||
|
|||
# fixme |
|||
*.lox |
|||
|
|||
# feynmf/feynmp |
|||
*.mf |
|||
*.mp |
|||
*.t[1-9] |
|||
*.t[1-9][0-9] |
|||
*.tfm |
|||
|
|||
#(r)(e)ledmac/(r)(e)ledpar |
|||
*.end |
|||
*.?end |
|||
*.[1-9] |
|||
*.[1-9][0-9] |
|||
*.[1-9][0-9][0-9] |
|||
*.[1-9]R |
|||
*.[1-9][0-9]R |
|||
*.[1-9][0-9][0-9]R |
|||
*.eledsec[1-9] |
|||
*.eledsec[1-9]R |
|||
*.eledsec[1-9][0-9] |
|||
*.eledsec[1-9][0-9]R |
|||
*.eledsec[1-9][0-9][0-9] |
|||
*.eledsec[1-9][0-9][0-9]R |
|||
|
|||
# glossaries |
|||
*.acn |
|||
*.acr |
|||
*.glg |
|||
*.glo |
|||
*.gls |
|||
*.glsdefs |
|||
*.lzo |
|||
*.lzs |
|||
|
|||
# uncomment this for glossaries-extra (will ignore makeindex's style files!) |
|||
# *.ist |
|||
|
|||
# gnuplottex |
|||
*-gnuplottex-* |
|||
|
|||
# gregoriotex |
|||
*.gaux |
|||
*.glog |
|||
*.gtex |
|||
|
|||
# htlatex |
|||
*.4ct |
|||
*.4tc |
|||
*.idv |
|||
*.lg |
|||
*.trc |
|||
*.xref |
|||
|
|||
# hyperref |
|||
*.brf |
|||
|
|||
# knitr |
|||
*-concordance.tex |
|||
# TODO Uncomment the next line if you use knitr and want to ignore its generated tikz files |
|||
# *.tikz |
|||
*-tikzDictionary |
|||
|
|||
# listings |
|||
*.lol |
|||
|
|||
# luatexja-ruby |
|||
*.ltjruby |
|||
|
|||
# makeidx |
|||
*.idx |
|||
*.ilg |
|||
*.ind |
|||
|
|||
# minitoc |
|||
*.maf |
|||
*.mlf |
|||
*.mlt |
|||
*.mtc[0-9]* |
|||
*.slf[0-9]* |
|||
*.slt[0-9]* |
|||
*.stc[0-9]* |
|||
|
|||
# minted |
|||
_minted* |
|||
*.pyg |
|||
|
|||
# morewrites |
|||
*.mw |
|||
|
|||
# newpax |
|||
*.newpax |
|||
|
|||
# nomencl |
|||
*.nlg |
|||
*.nlo |
|||
*.nls |
|||
|
|||
# pax |
|||
*.pax |
|||
|
|||
# pdfpcnotes |
|||
*.pdfpc |
|||
|
|||
# sagetex |
|||
*.sagetex.sage |
|||
*.sagetex.py |
|||
*.sagetex.scmd |
|||
|
|||
# scrwfile |
|||
*.wrt |
|||
|
|||
# sympy |
|||
*.sout |
|||
*.sympy |
|||
sympy-plots-for-*.tex/ |
|||
|
|||
# pdfcomment |
|||
*.upa |
|||
*.upb |
|||
|
|||
# pythontex |
|||
*.pytxcode |
|||
pythontex-files-*/ |
|||
|
|||
# tcolorbox |
|||
*.listing |
|||
|
|||
# thmtools |
|||
*.loe |
|||
|
|||
# TikZ & PGF |
|||
*.dpth |
|||
*.md5 |
|||
*.auxlock |
|||
|
|||
# todonotes |
|||
*.tdo |
|||
|
|||
# vhistory |
|||
*.hst |
|||
*.ver |
|||
|
|||
# easy-todo |
|||
*.lod |
|||
|
|||
# xcolor |
|||
*.xcp |
|||
|
|||
# xmpincl |
|||
*.xmpi |
|||
|
|||
# xindy |
|||
*.xdy |
|||
|
|||
# xypic precompiled matrices and outlines |
|||
*.xyc |
|||
*.xyd |
|||
|
|||
# endfloat |
|||
*.ttt |
|||
*.fff |
|||
|
|||
# Latexian |
|||
TSWLatexianTemp* |
|||
|
|||
## Editors: |
|||
# WinEdt |
|||
*.bak |
|||
*.sav |
|||
|
|||
# Texpad |
|||
.texpadtmp |
|||
|
|||
# LyX |
|||
*.lyx~ |
|||
|
|||
# Kile |
|||
*.backup |
|||
|
|||
# gummi |
|||
.*.swp |
|||
|
|||
# KBibTeX |
|||
*~[0-9]* |
|||
|
|||
# TeXnicCenter |
|||
*.tps |
|||
|
|||
# auto folder when using emacs and auctex |
|||
./auto/* |
|||
*.el |
|||
|
|||
# expex forward references with \gathertags |
|||
*-tags.tex |
|||
|
|||
# standalone packages |
|||
*.sta |
|||
|
|||
# Makeindex log files |
|||
*.lpz |
|||
|
|||
# xwatermark package |
|||
*.xwm |
|||
|
|||
# REVTeX puts footnotes in the bibliography by default, unless the nofootinbib |
|||
# option is specified. Footnotes are the stored in a file with suffix Notes.bib. |
|||
# Uncomment the next line to have this generated file ignored. |
|||
#*Notes.bib |
|||
|
|||
### LaTeX Patch ### |
|||
# LIPIcs / OASIcs |
|||
*.vtc |
|||
|
|||
# glossaries |
|||
*.glstex |
|||
|
|||
# End of https://www.toptal.com/developers/gitignore/api/latex |
@ -0,0 +1,24 @@ |
|||
# LaTeXmk configuration file |
|||
|
|||
# Usage example |
|||
# latexmk file.tex |
|||
|
|||
# Main command line options |
|||
# -pdf : generate pdf using pdflatex |
|||
# -pv : run file previewer |
|||
# -pvc : run file previewer and continually recompile on change |
|||
# -C : clean up by removing all regeneratable files |
|||
|
|||
# Generate pdf using pdflatex (-pdf) |
|||
$pdf_mode = 1; |
|||
|
|||
# Define command to compile with pdfsync support and nonstopmode |
|||
$pdflatex = 'lualatex -shell-escape'; |
|||
|
|||
# Use default pdf viewer (Skim) |
|||
$pdf_previewer = 'evince'; |
|||
|
|||
# Also remove pdfsync files on clean |
|||
$clean_ext = 'pdfsync synctex.gz'; |
|||
|
|||
$ENV{'TEXINPUTS'}='/home/klafyvel/Documents/asso/rezo/formations/SystèmePaiementRe2o/rmrf-latex:' . $ENV{'TEXINPUTS'}; |
@ -0,0 +1,14 @@ |
|||
# Makefile for presentation
|
|||
|
|||
.PHONY: presentation.pdf all clean |
|||
|
|||
all: presentation.pdf |
|||
|
|||
presentation.pdf: presentation.tex |
|||
latexmk -use-make $< |
|||
|
|||
cleanall: |
|||
latexmk -C |
|||
|
|||
clean: |
|||
latexmk -c |
Binary file not shown.
@ -0,0 +1,326 @@ |
|||
\documentclass[10pt,xcolor={table,dvipsnames},t, aspectratio=169]{beamer} |
|||
\usepackage{minted} |
|||
|
|||
\usetheme{rmrf} |
|||
|
|||
\title{Re2o et les cotisations} |
|||
\subtitle{Rézo Rennes et Metz Fédérés} |
|||
\author{Klafyvel} |
|||
\date{10/07/2021} |
|||
|
|||
\begin{document} |
|||
|
|||
\begin{frame} |
|||
\titlepage |
|||
\end{frame} |
|||
|
|||
\begin{frame}{Sommaire} |
|||
\tableofcontents |
|||
\end{frame} |
|||
|
|||
|
|||
\begin{frame} |
|||
\vspace{2cm} |
|||
\centering{\Huge\textbf{Contrainte principale :}\\Ne pas faire de la merde avec les sous des adhérents.} |
|||
\end{frame} |
|||
|
|||
\section{Les principales structures de données} |
|||
|
|||
\begin{frame}[fragile]{L'objet Facture} |
|||
\begin{columns} |
|||
\begin{column}{0.5\textwidth} |
|||
\begin{itemize} |
|||
\item<1-> Représente une facture; |
|||
\item<2-> Visible par les adhérents; |
|||
\item<3-> Est censé être controlée par les trésoriers. |
|||
\end{itemize} |
|||
\end{column} |
|||
\begin{column}{0.5\textwidth} |
|||
\begin{minted}[fontsize=\footnotesize,]{python} |
|||
class Facture(BaseInvoice): |
|||
user = models.ForeignKey("users.User",...) |
|||
paiement = models.ForeignKey("Paiement", ...) |
|||
banque = models.ForeignKey("Banque", ...) |
|||
cheque = models.CharField(...) |
|||
valid = models.BooleanField(...) |
|||
control = models.BooleanField(...) |
|||
\end{minted} |
|||
\end{column} |
|||
\end{columns} |
|||
\end{frame} |
|||
\begin{frame}[fragile]{L'objet Vente} |
|||
\begin{columns} |
|||
\begin{column}{0.5\textwidth} |
|||
\begin{itemize} |
|||
\item Représente une vente de \verb|number| articles(s) au prix unitaire \verb|prix|; |
|||
\item Stocke une information sur la durée d'adhésion / cotisation. |
|||
\end{itemize} |
|||
\end{column} |
|||
\begin{column}{0.5\textwidth} |
|||
\begin{minted}[fontsize=\footnotesize,]{python} |
|||
class Vente(RevMixin, AclMixin, models.Model): |
|||
facture = models.ForeignKey("BaseInvoice", ...) |
|||
number = models.IntegerField(...) |
|||
name = models.CharField(...) |
|||
prix = models.DecimalField(...) |
|||
duration_connection = models.PositiveIntegerField(...) |
|||
duration_days_connection = models.PositiveIntegerField(...) |
|||
duration_membership = models.PositiveIntegerField(...) |
|||
duration_days_membership = models.PositiveIntegerField(...) |
|||
\end{minted} |
|||
\end{column} |
|||
\end{columns} |
|||
\end{frame} |
|||
\begin{frame}[fragile]{L'objet Article} |
|||
\begin{columns} |
|||
\begin{column}{0.5\textwidth} |
|||
\begin{itemize} |
|||
\item Une recette pour créer des \verb|Vente|s; |
|||
\item On ne lie pas directement les ventes aux articles, on peut supprimer les articles sans contrainte. |
|||
\end{itemize} |
|||
\end{column} |
|||
\begin{column}{0.5\textwidth} |
|||
\begin{minted}[fontsize=\footnotesize,]{python} |
|||
class Article(RevMixin, AclMixin, models.Model): |
|||
name = models.CharField(...) |
|||
prix = models.DecimalField(...) |
|||
duration_membership = models.PositiveIntegerField(...) |
|||
duration_days_membership = models.PositiveIntegerField(...) |
|||
duration_connection = models.PositiveIntegerField(...) |
|||
duration_days_connection = models.PositiveIntegerField(...) |
|||
need_membership = models.BooleanField(...) |
|||
type_user = models.CharField(...) |
|||
available_for_everyone = models.BooleanField(...) |
|||
\end{minted} |
|||
\end{column} |
|||
\end{columns} |
|||
\end{frame} |
|||
\begin{frame}[fragile]{L'objet Cotisation} |
|||
\begin{columns} |
|||
\begin{column}{0.5\textwidth} |
|||
\begin{itemize} |
|||
\item Information sur les adhésions / cotisations des utilisateurs; |
|||
\item C’est ce qui est utilisé par l’objet \verb|User| pour savoir si un utilisateur est adhérent. |
|||
\end{itemize} |
|||
\end{column} |
|||
\begin{column}{0.5\textwidth} |
|||
\begin{minted}[fontsize=\footnotesize,]{python} |
|||
class Cotisation(RevMixin, AclMixin, models.Model): |
|||
vente = models.OneToOneField("Vente",...) |
|||
date_start_con = models.DateTimeField(...) |
|||
date_end_con = models.DateTimeField(...) |
|||
date_start_memb = models.DateTimeField(...) |
|||
date_end_memb = models.DateTimeField(...) |
|||
\end{minted} |
|||
\end{column} |
|||
\end{columns} |
|||
\end{frame} |
|||
\begin{frame}[fragile]{L'objet Paiement} |
|||
\begin{columns} |
|||
\begin{column}{0.5\textwidth} |
|||
\begin{itemize} |
|||
\item Enregistre un moyen de paiement; |
|||
\item On peut y brancher des méthodes de paiement personnalisées. |
|||
\end{itemize} |
|||
\end{column} |
|||
\begin{column}{0.5\textwidth} |
|||
\begin{minted}[fontsize=\footnotesize,]{python} |
|||
class Paiement(RevMixin, AclMixin, models.Model): |
|||
moyen = models.CharField(...) |
|||
available_for_everyone = models.BooleanField(...) |
|||
is_balance = models.BooleanField(...) |
|||
\end{minted} |
|||
\end{column} |
|||
\end{columns} |
|||
\end{frame} |
|||
|
|||
\section{La vue new\_facture} |
|||
|
|||
\begin{frame}[fragile] |
|||
\begin{columns} |
|||
\begin{column}{0.5\textwidth} |
|||
\begin{minted}[fontsize=\footnotesize,]{python} |
|||
@login_required |
|||
@can_create(Facture) |
|||
@can_edit(User) |
|||
def new_facture(request, user, userid): |
|||
"""De la doc...""" |
|||
invoice = Facture(user=user) |
|||
article_list = Article.objects.filter(...) |
|||
invoice_form = FactureForm(...) |
|||
article_formset = formset_factory(SelectArticleForm)(...) |
|||
if invoice_form.is_valid() and article_formset.is_valid(): |
|||
# On verra après |
|||
|
|||
# Gestion du solde |
|||
p = Paiement.objects.filter(is_balance=True) |
|||
if len(p) and p[0].can_use_payment(request.user): |
|||
balance = user.solde |
|||
else: |
|||
balance = None |
|||
|
|||
return form(...) |
|||
\end{minted} |
|||
\end{column} |
|||
\begin{column}{0.5\textwidth} |
|||
Vue assez classique de formulaire Django. |
|||
\end{column} |
|||
\end{columns} |
|||
\end{frame} |
|||
|
|||
\begin{frame}[fragile]{À l'intérieur de ce if} |
|||
\begin{minted}[fontsize=\footnotesize,]{python} |
|||
new_invoice_instance = invoice_form.save(commit=False) |
|||
articles = article_formset |
|||
# Check if at least one article has been selected |
|||
if any(art.cleaned_data for art in articles): |
|||
# Encore un peu de patience, slide suivante |
|||
else : |
|||
messages.error(request, _("You need to choose at least one article.")) |
|||
\end{minted} |
|||
\end{frame} |
|||
\begin{frame} |
|||
\vspace{2cm} |
|||
\centering{\Huge\textbf{Roulement de tambours...}} |
|||
\end{frame} |
|||
|
|||
\begin{frame}[fragile] |
|||
\begin{columns} |
|||
\begin{column}{0.5\textwidth} |
|||
\begin{minted}[fontsize=\footnotesize,]{python} |
|||
# Building a purchase for each article sold |
|||
purchases = [] |
|||
total_price = 0 |
|||
for art_item in articles: |
|||
if art_item.cleaned_data: |
|||
article = art_item.cleaned_data["article"] |
|||
quantity = art_item.cleaned_data["quantity"] |
|||
total_price += article.prix * quantity |
|||
new_purchase = Vente(...) |
|||
purchases.append(new_purchase) |
|||
p = find_payment_method(new_invoice_instance.paiement) |
|||
if hasattr(p, "check_price"): |
|||
price_ok, msg = p.check_price(total_price, user) |
|||
invoice_form.add_error(None, msg) |
|||
else: |
|||
price_ok = True |
|||
\end{minted} |
|||
\end{column} |
|||
\begin{column}{0.5\textwidth} |
|||
|
|||
\begin{minted}[fontsize=\footnotesize,]{python} |
|||
if price_ok: |
|||
new_invoice_instance.save() |
|||
# Saving purchases so the invoice can find them. Invoice |
|||
# will modify them after being validated to put the right dates. |
|||
for p in purchases: |
|||
p.facture = new_invoice_instance |
|||
p.save() |
|||
return new_invoice_instance.paiement.end_payment( |
|||
new_invoice_instance, request |
|||
) |
|||
\end{minted} |
|||
\end{column} |
|||
\end{columns} |
|||
\end{frame} |
|||
|
|||
\begin{frame}[fragile]{Le retour du modèle Paiement} |
|||
\begin{columns} |
|||
\begin{column}{0.5\textwidth} |
|||
Pour finir un paiement, |
|||
\begin{itemize} |
|||
\item Si une méthode de paiement personnalisée existe et que la transisition n'est pas explicitement interdite, on branche; |
|||
\item Sinon on valide la facture, on affiche un message et on redirige. |
|||
\end{itemize} |
|||
\end{column} |
|||
\begin{column}{0.5\textwidth} |
|||
\begin{minted}[fontsize=\footnotesize,]{python} |
|||
def end_payment(self, invoice, request, |
|||
use_payment_method=True): |
|||
payment_method = find_payment_method(self) |
|||
if payment_method is not None \ |
|||
and use_payment_method: |
|||
return payment_method.end_payment(invoice, |
|||
request) |
|||
|
|||
# So make this invoice valid, trigger send mail |
|||
invoice.valid = True |
|||
invoice.save(request=request) |
|||
|
|||
# Du code pas intéressant |
|||
return redirect(...) |
|||
\end{minted} |
|||
\end{column} |
|||
\end{columns} |
|||
\end{frame} |
|||
|
|||
\section{Un exemple simple : FreePayment} |
|||
|
|||
\begin{frame}[fragile] |
|||
\begin{columns} |
|||
\begin{column}{0.5\textwidth} |
|||
\begin{minted}[fontsize=\footnotesize,]{python} |
|||
class FreePayment(PaymentMethodMixin, models.Model): |
|||
"""...""" |
|||
|
|||
class Meta: |
|||
verbose_name = _("Free payment") |
|||
|
|||
payment = models.OneToOneField( |
|||
Paiement, |
|||
on_delete=models.CASCADE, |
|||
related_name="payment_method_free", |
|||
editable=False, |
|||
) |
|||
\end{minted} |
|||
\end{column} |
|||
\begin{column}{0.5\textwidth} |
|||
\begin{minted}[fontsize=\footnotesize,]{python} |
|||
def end_payment(self, invoice, request): |
|||
"""Ends the payment normally. |
|||
""" |
|||
return invoice.paiement.end_payment(invoice, |
|||
request, |
|||
use_payment_method=False |
|||
) |
|||
|
|||
def check_price(self, price, user, *args, **kwargs): |
|||
"""Checks that the price meets the requirement |
|||
to be paid with user balance. |
|||
""" |
|||
return ( |
|||
price == 0, |
|||
_("You can't pay this invoice for free.") |
|||
) |
|||
\end{minted} |
|||
\end{column} |
|||
\end{columns} |
|||
\end{frame} |
|||
|
|||
\section{Un exemple intéressant : ComnPay} |
|||
|
|||
\begin{frame}{Déroulé} |
|||
\begin{itemize} |
|||
\item<2-> Le end\_payment construit une requête spéciale pour que l'utilisateur l'envoie vers comnpay. La facture est invalide; |
|||
\item<3-> L'utilisateur fait son affaire avec ComnPay; |
|||
\item<4-> ComnPay notifie re2o que le paiement a été effectué. La facture est validée; |
|||
\item<5-> L'utilisateur est redirigé vers re2o. |
|||
\end{itemize} |
|||
\end{frame} |
|||
|
|||
\begin{frame} |
|||
\vspace{2cm} |
|||
\centering{\Huge\textbf{Un petit tour dans le code.}} |
|||
\end{frame} |
|||
|
|||
\section{Conclusion} |
|||
|
|||
\begin{frame}{Conclusion} |
|||
\begin{itemize} |
|||
\item Le système de paiement est modulable; |
|||
\item Mais du coup il est complexe; |
|||
\item Pour intégrer HelloAsso il faudrait s'inspirer du système ComnPay. |
|||
\end{itemize} |
|||
\end{frame} |
|||
|
|||
\end{document} |
Loading…
Reference in new issue