Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
R
re2o
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Nounous
re2o
Commits
48d8d792
Commit
48d8d792
authored
Jan 05, 2019
by
Hugo LEVY-FALK
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
subscripbtion voucher
parent
0a8335c3
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
217 additions
and
29 deletions
+217
-29
cotisations/admin.py
cotisations/admin.py
+1
-2
cotisations/forms.py
cotisations/forms.py
+1
-2
cotisations/models.py
cotisations/models.py
+52
-0
cotisations/tex.py
cotisations/tex.py
+21
-21
cotisations/utils.py
cotisations/utils.py
+53
-0
cotisations/views.py
cotisations/views.py
+3
-2
preferences/migrations/0057_cotisationsoption.py
preferences/migrations/0057_cotisationsoption.py
+38
-0
preferences/models.py
preferences/models.py
+6
-1
users/models.py
users/models.py
+20
-1
users/templates/users/email_subscription_accepted
users/templates/users/email_subscription_accepted
+22
-0
No files found.
cotisations/admin.py
View file @
48d8d792
...
...
@@ -30,8 +30,7 @@ from django.contrib import admin
from
reversion.admin
import
VersionAdmin
from
.models
import
Facture
,
Article
,
Banque
,
Paiement
,
Cotisation
,
Vente
from
.models
import
CustomInvoice
,
CostEstimate
from
.tex
import
DocumentTemplate
from
.models
import
CustomInvoice
,
CostEstimate
,
DocumentTemplate
class
FactureAdmin
(
VersionAdmin
):
...
...
cotisations/forms.py
View file @
48d8d792
...
...
@@ -48,9 +48,8 @@ from re2o.field_permissions import FieldPermissionFormMixin
from
re2o.mixins
import
FormRevMixin
from
.models
import
(
Article
,
Paiement
,
Facture
,
Banque
,
CustomInvoice
,
Vente
,
CostEstimate
CustomInvoice
,
Vente
,
CostEstimate
,
DocumentTemplate
)
from
.tex
import
DocumentTemplate
from
.payment_methods
import
balance
...
...
cotisations/models.py
View file @
48d8d792
...
...
@@ -236,11 +236,23 @@ class Facture(BaseInvoice):
'control'
:
self
.
can_change_control
,
}
self
.
__original_valid
=
self
.
valid
self
.
__original_control
=
self
.
control
def
get_subscribtion
(
self
):
return
self
.
vent_set
.
filter
(
Q
(
type_cotisation
=
'All'
)
|
Q
(
type_cotisation
=
'Cotisation'
)
)
def
is_subscribtion
(
self
):
return
bool
(
self
.
get_subscribtion
())
def
save
(
self
,
*
args
,
**
kwargs
):
super
(
Facture
,
self
).
save
(
*
args
,
**
kwargs
)
if
not
self
.
__original_valid
and
self
.
valid
:
send_mail_invoice
(
self
)
if
self
.
is_subscribtion
()
and
not
self
.
__original_control
and
self
.
control
:
send_mail_voucher
(
self
)
def
__str__
(
self
):
return
str
(
self
.
user
)
+
' '
+
str
(
self
.
date
)
...
...
@@ -255,6 +267,10 @@ def facture_post_save(**kwargs):
user
=
facture
.
user
user
.
set_active
()
user
.
ldap_sync
(
base
=
False
,
access_refresh
=
True
,
mac_refresh
=
False
)
if
facture
.
control
:
user
=
facture
.
user
if
user
.
is_adherent
():
user
.
notif_subscription_accepted
()
@
receiver
(
post_delete
,
sender
=
Facture
)
...
...
@@ -935,3 +951,39 @@ def cotisation_post_delete(**_kwargs):
"""
regen
(
'mac_ip_list'
)
regen
(
'mailing'
)
class
DocumentTemplate
(
RevMixin
,
AclMixin
,
models
.
Model
):
"""Represent a template in order to create documents such as invoice or
subscribtion voucher.
"""
template
=
models
.
FileField
(
upload_to
=
'templates/'
,
verbose_name
=
_
(
'template'
)
)
name
=
models
.
CharField
(
max_length
=
255
,
verbose_name
=
_
(
'name'
)
)
class
Meta
:
verbose_name
=
_
(
"document template"
)
verbose_name_plural
=
_
(
"document templates"
)
def
__str__
(
self
):
return
str
(
self
.
name
)
class
Voucher
(
RevMixin
,
AclMixin
,
models
.
Model
):
"""A Subscription Voucher."""
user
=
models
.
ForeignKey
(
'users.User'
,
on_delete
=
models
.
CASCADE
,
verbose_name
=
_
(
"user"
)
)
class
Meta
:
verbose_name
=
_
(
"subscription voucher"
)
def
__str__
(
self
):
return
"voucher {} {}"
.
format
(
self
.
user
,
self
.
date
)
cotisations/tex.py
View file @
48d8d792
...
...
@@ -48,27 +48,6 @@ CACHE_PREFIX = getattr(settings, 'TEX_CACHE_PREFIX', 'render-tex')
CACHE_TIMEOUT
=
getattr
(
settings
,
'TEX_CACHE_TIMEOUT'
,
86400
)
# 1 day
class
DocumentTemplate
(
RevMixin
,
AclMixin
,
models
.
Model
):
"""Represent a template in order to create documents such as invoice or
subscribtion voucher.
"""
template
=
models
.
FileField
(
upload_to
=
'templates/'
,
verbose_name
=
_
(
'template'
)
)
name
=
models
.
CharField
(
max_length
=
255
,
verbose_name
=
_
(
'name'
)
)
class
Meta
:
verbose_name
=
_
(
"document template"
)
verbose_name_plural
=
_
(
"document templates"
)
def
__str__
(
self
):
return
str
(
self
.
name
)
def
render_invoice
(
_request
,
ctx
=
{}):
"""
Render an invoice using some available information such as the current
...
...
@@ -92,6 +71,27 @@ def render_invoice(_request, ctx={}):
return
r
def
render_voucher
(
_request
,
ctx
=
{}):
"""
Render a subscribtion voucher.
"""
options
,
_
=
CotisationsOption
.
objects
.
get_or_create
()
filename
=
'_'
.
join
([
'voucher'
,
slugify
(
ctx
.
get
(
'asso_name'
,
""
)),
slugify
(
ctx
.
get
(
'recipient_name'
,
""
)),
str
(
ctx
.
get
(
'DATE'
,
datetime
.
now
()).
year
),
str
(
ctx
.
get
(
'DATE'
,
datetime
.
now
()).
month
),
str
(
ctx
.
get
(
'DATE'
,
datetime
.
now
()).
day
),
])
templatename
=
options
.
voucher_template
.
template
.
name
.
split
(
'/'
)[
-
1
]
r
=
create_pdf
(
templatename
,
ctx
)
r
[
'Content-Disposition'
]
=
'attachment; filename="{name}.pdf"'
.
format
(
name
=
filename
)
return
r
def
create_pdf
(
template
,
ctx
=
{}):
"""Creates and returns a PDF from a LaTeX template using pdflatex.
...
...
cotisations/utils.py
View file @
48d8d792
...
...
@@ -93,3 +93,56 @@ def send_mail_invoice(invoice):
attachments
=
[(
'invoice.pdf'
,
pdf
,
'application/pdf'
)]
)
mail
.
send
()
def
send_mail_voucher
(
invoice
):
"""Creates a voucher from an invoice and sends it by email to the client"""
purchases_info
=
[]
for
purchase
in
invoice
.
vente_set
.
all
():
purchases_info
.
append
({
'name'
:
purchase
.
name
,
'price'
:
purchase
.
prix
,
'quantity'
:
purchase
.
number
,
'total_price'
:
purchase
.
prix_total
})
ctx
=
{
'paid'
:
True
,
'fid'
:
invoice
.
id
,
'DATE'
:
invoice
.
date
,
'recipient_name'
:
"{} {}"
.
format
(
invoice
.
user
.
name
,
invoice
.
user
.
surname
),
'address'
:
invoice
.
user
.
room
,
'article'
:
purchases_info
,
'total'
:
invoice
.
prix_total
(),
'asso_name'
:
AssoOption
.
get_cached_value
(
'name'
),
'line1'
:
AssoOption
.
get_cached_value
(
'adresse1'
),
'line2'
:
AssoOption
.
get_cached_value
(
'adresse2'
),
'siret'
:
AssoOption
.
get_cached_value
(
'siret'
),
'email'
:
AssoOption
.
get_cached_value
(
'contact'
),
'phone'
:
AssoOption
.
get_cached_value
(
'telephone'
),
'tpl_path'
:
os
.
path
.
join
(
settings
.
BASE_DIR
,
LOGO_PATH
)
}
pdf
=
create_pdf
(
'cotisations/factures.tex'
,
ctx
)
template
=
get_template
(
'cotisations/email_invoice'
)
ctx
=
{
'name'
:
"{} {}"
.
format
(
invoice
.
user
.
name
,
invoice
.
user
.
surname
),
'contact_mail'
:
AssoOption
.
get_cached_value
(
'contact'
),
'asso_name'
:
AssoOption
.
get_cached_value
(
'name'
)
}
mail
=
EmailMessage
(
'Votre facture / Your invoice'
,
template
.
render
(
ctx
),
GeneralOption
.
get_cached_value
(
'email_from'
),
[
invoice
.
user
.
get_mail
],
attachments
=
[(
'invoice.pdf'
,
pdf
,
'application/pdf'
)]
)
mail
.
send
()
cotisations/views.py
View file @
48d8d792
...
...
@@ -69,7 +69,8 @@ from .models import (
Banque
,
CustomInvoice
,
BaseInvoice
,
CostEstimate
CostEstimate
,
DocumentTemplate
)
from
.forms
import
(
FactureForm
,
...
...
@@ -87,7 +88,7 @@ from .forms import (
DocumentTemplateForm
,
DelDocumentTemplateForm
)
from
.tex
import
render_invoice
,
escape_chars
,
DocumentTemplate
from
.tex
import
render_invoice
,
escape_chars
from
.payment_methods.forms
import
payment_method_factory
from
.utils
import
find_payment_method
...
...
preferences/migrations/0057_cotisationsoption.py
0 → 100644
View file @
48d8d792
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2019-01-03 19:56
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
import
django.db.models.deletion
import
re2o.mixins
def
initialize_invoice_template
(
apps
,
schema_editor
):
CotisationsOption
=
apps
.
get_model
(
'preferences'
,
'CotisationsOption'
)
DocumentTemplate
=
apps
.
get_model
(
'cotisations'
,
'DocumentTemplate'
)
CotisationsOption
.
objects
.
create
(
invoice_template
=
DocumentTemplate
.
objects
.
first
()
)
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'cotisations'
,
'0039_documenttemplate'
),
(
'preferences'
,
'0056_4_radiusoption'
),
]
operations
=
[
migrations
.
CreateModel
(
name
=
'CotisationsOption'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
verbose_name
=
'ID'
)),
(
'invoice_template'
,
models
.
OneToOneField
(
on_delete
=
django
.
db
.
models
.
deletion
.
PROTECT
,
related_name
=
'invoice_template'
,
to
=
'cotisations.DocumentTemplate'
,
verbose_name
=
'Template for invoices'
)),
],
options
=
{
'verbose_name'
:
'cotisations options'
,
},
bases
=
(
re2o
.
mixins
.
AclMixin
,
models
.
Model
),
),
migrations
.
RunPython
(
initialize_invoice_template
),
]
preferences/models.py
View file @
48d8d792
...
...
@@ -698,4 +698,9 @@ class CotisationsOption(AclMixin, PreferencesModel):
related_name
=
"invoice_template"
,
on_delete
=
models
.
PROTECT
,
)
voucher_template
=
models
.
OneToOneField
(
'cotisations.DocumentTemplate'
,
verbose_name
=
_
(
"Template for subscription voucher"
),
related_name
=
"voucher_template"
,
on_delete
=
models
.
PROTECT
,
)
users/models.py
View file @
48d8d792
...
...
@@ -663,7 +663,26 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
)
return
def
reset_passwd_mail
(
self
,
request
):
def
notif_subscription_accepted
(
self
):
"""Send an email when the subscription has been accepted"""
template
=
loader
.
get_template
(
'users/email_subscription_accepted'
)
mailmessageoptions
,
_created
=
MailMessageOption
\
.
objects
.
get_or_create
()
context
=
Context
({
'nom'
:
self
.
get_full_name
(),
'asso_name'
:
AssoOption
.
get_cached_value
(
'name'
),
'asso_email'
:
AssoOption
.
get_cached_value
(
'contact'
),
})
send_mail
(
'Votre inscription a été validée / Your subscription has been accepted'
,
''
,
GeneralOption
.
get_cached_value
(
'email_from'
),
[
self
.
email
],
html_message
=
template
.
render
(
context
)
)
return
def
reset_passwd_mail
(
self
,
request
):
""" Prend en argument un request, envoie un mail de
réinitialisation de mot de pass """
req
=
Request
()
...
...
users/templates/users/email_subscription_accepted
0 → 100644
View file @
48d8d792
<p>Bonjour {{nom}} !</p>
<p>Nous vous informons que votre cotisation auprès de {{asso_name}} a été acceptée. Vous voilà donc membre de l'association.</p>
<p>Vous trouverez en pièce jointe un reçu.</p>
<p>Pour nous faire part de toute remarque, suggestion ou problème vous pouvez nous envoyer un mail à {{asso_email}}.</p>
<p>À bientôt,<br>
L'équipe de {{asso_name}}.</p>
<p>---</p>
<p>Your subscription to {{asso_name}} has just been accepted. You are now a full member of {{asso_name}}.
<p>You will find with this email a subscription voucher.</p>
<p>For any information, suggestion or problem, you can contact us via email at<br>
{{asso_email}}.</p>
<p>Regards,<br>
The {{asso_name}} team.</p>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment