Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
re2o
Project overview
Project overview
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
36
Issues
36
List
Boards
Labels
Milestones
Merge Requests
8
Merge Requests
8
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
federez
re2o
Commits
48d8d792
Commit
48d8d792
authored
Jan 05, 2019
by
klafyvel
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