commit creditnote stuff
This commit is contained in:
parent
da4843bb06
commit
c6d4c1edc3
|
@ -7,6 +7,7 @@ admin.site.register(models.EpayPayment)
|
|||
admin.site.register(models.CoinifyAPIInvoice)
|
||||
admin.site.register(models.CoinifyAPICallback)
|
||||
admin.site.register(models.Invoice)
|
||||
admin.site.register(models.CreditNote)
|
||||
|
||||
|
||||
@admin.register(models.ProductCategory)
|
||||
|
@ -55,12 +56,12 @@ class OrderAdmin(admin.ModelAdmin):
|
|||
]
|
||||
|
||||
list_filter = [
|
||||
'user',
|
||||
'camp',
|
||||
'payment_method',
|
||||
'open',
|
||||
'paid',
|
||||
'cancelled',
|
||||
'user',
|
||||
]
|
||||
|
||||
exclude = ['products']
|
||||
|
|
|
@ -11,6 +11,10 @@ def send_email(emailtype, recipient, formatdict, subject, sender='BornHack <info
|
|||
text_template = 'emails/invoice_email.txt'
|
||||
html_template = 'emails/invoice_email.html'
|
||||
attachment_filename = formatdict['filename']
|
||||
if emailtype == 'creditnote':
|
||||
text_template = 'emails/creditnote_email.txt'
|
||||
html_template = 'emails/creditnote_email.html'
|
||||
attachment_filename = formatdict['creditnote'].filename
|
||||
elif emailtype == 'testmail':
|
||||
text_template = 'emails/testmail.txt'
|
||||
else:
|
||||
|
@ -40,6 +44,24 @@ def send_email(emailtype, recipient, formatdict, subject, sender='BornHack <info
|
|||
return True
|
||||
|
||||
|
||||
def send_creditnote_email(creditnote):
|
||||
# put formatdict together
|
||||
formatdict = {
|
||||
'creditnote': creditnote,
|
||||
}
|
||||
|
||||
subject = 'BornHack creditnote %s' % creditnote.pk
|
||||
|
||||
# send mail
|
||||
return send_email(
|
||||
emailtype='creditnote',
|
||||
recipient=creditnote.user.email,
|
||||
formatdict=formatdict,
|
||||
subject=subject,
|
||||
sender='info@bornhack.dk',
|
||||
attachment=creditnote.pdf.read(),
|
||||
)
|
||||
|
||||
def send_invoice_email(invoice):
|
||||
# put formatdict together
|
||||
formatdict = {
|
||||
|
|
|
@ -3,15 +3,15 @@ from django.core.files import File
|
|||
from django.conf import settings
|
||||
from django.utils import timezone
|
||||
from shop.pdf import generate_pdf_letter
|
||||
from shop.email import send_invoice_email
|
||||
from shop.models import Order, Invoice
|
||||
from shop.email import send_invoice_email, send_creditnote_email
|
||||
from shop.models import Order, Invoice, CreditNote
|
||||
from time import sleep
|
||||
from decimal import Decimal
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
args = 'none'
|
||||
help = 'Send out invoices that have not been sent yet'
|
||||
help = 'Generate invoices and credit notes, and email invoices that have not been sent yet'
|
||||
|
||||
def output(self, message):
|
||||
self.stdout.write('%s: %s' % (timezone.now().strftime("%Y-%m-%d %H:%M:%S"), message))
|
||||
|
@ -53,6 +53,7 @@ class Command(BaseCommand):
|
|||
invoice.pdf.save(invoice.filename, File(pdffile))
|
||||
invoice.save()
|
||||
|
||||
###############################################################
|
||||
# check if we need to send out any invoices (only where pdf has been generated)
|
||||
for invoice in Invoice.objects.filter(sent_to_customer=False).exclude(pdf=''):
|
||||
# send the email
|
||||
|
@ -63,6 +64,46 @@ class Command(BaseCommand):
|
|||
else:
|
||||
self.output('ERROR: Unable to send invoice email for order %s to %s' % (invoice.order.pk, invoice.order.user.email))
|
||||
|
||||
###############################################################
|
||||
# check if we need to generate any pdf creditnotes?
|
||||
for creditnote in CreditNote.objects.filter(pdf=''):
|
||||
# put the dict with data for the pdf together
|
||||
formatdict = {
|
||||
'creditnote': creditnote,
|
||||
}
|
||||
|
||||
# generate the pdf
|
||||
try:
|
||||
pdffile = generate_pdf_letter(
|
||||
filename=creditnote.filename,
|
||||
template='pdf/creditnote.html',
|
||||
formatdict=formatdict,
|
||||
)
|
||||
self.output('Generated pdf for creditnote %s' % creditnote)
|
||||
except Exception as E:
|
||||
self.output('ERROR: Unable to generate PDF file for creditnote #%s. Error: %s' % (creditnote.pk, E))
|
||||
continue
|
||||
|
||||
# so, do we have a pdf?
|
||||
if not pdffile:
|
||||
self.output('ERROR: Unable to generate PDF file for creditnote #%s' % creditnote.pk)
|
||||
continue
|
||||
|
||||
# update creditnote object with the file
|
||||
creditnote.pdf.save(creditnote.filename, File(pdffile))
|
||||
creditnote.save()
|
||||
|
||||
###############################################################
|
||||
# check if we need to send out any creditnotes (only where pdf has been generated)
|
||||
for creditnote in CreditNote.objects.filter(sent_to_customer=False).exclude(pdf=''):
|
||||
# send the email
|
||||
if send_creditnote_email(creditnote=creditnote):
|
||||
self.output('OK: Creditnote email sent to %s' % creditnote.user.email)
|
||||
creditnote.sent_to_customer=True
|
||||
creditnote.save()
|
||||
else:
|
||||
self.output('ERROR: Unable to send creditnote email for creditnote %s to %s' % (creditnote.pk, creditnote.user.email))
|
||||
|
||||
# pause for a bit
|
||||
sleep(60)
|
||||
|
||||
|
|
|
@ -25,12 +25,6 @@ class Order(CreatedUpdatedModel):
|
|||
through='shop.OrderProductRelation'
|
||||
)
|
||||
|
||||
user = models.ForeignKey(
|
||||
'auth.User',
|
||||
verbose_name=_('User'),
|
||||
help_text=_('The user this order belongs to.'),
|
||||
related_name='orders',
|
||||
)
|
||||
|
||||
paid = models.BooleanField(
|
||||
verbose_name=_('Paid?'),
|
||||
|
@ -264,17 +258,55 @@ class EpayPayment(CreatedUpdatedModel, UUIDModel):
|
|||
txnid = models.IntegerField()
|
||||
|
||||
|
||||
class CreditNote(CreatedUpdatedModel):
|
||||
amount = models.DecimalField()
|
||||
text = models.TextField()
|
||||
pdf = models.FileField(
|
||||
null=True,
|
||||
blank=True,
|
||||
upload_to='creditnotes/'
|
||||
)
|
||||
user = models.ForeignKey(
|
||||
'auth.User',
|
||||
verbose_name=_('User'),
|
||||
help_text=_('The user this credit note belongs to.'),
|
||||
related_name='creditnotes',
|
||||
)
|
||||
paid = models.BooleanField(
|
||||
verbose_name=_('Paid?'),
|
||||
help_text=_('Whether this creditnote has been paid.'),
|
||||
default=False,
|
||||
)
|
||||
sent_to_customer = models.BooleanField(default=False)
|
||||
|
||||
def __str__(self):
|
||||
return 'creditnote#%s - %s DKK (sent to %s: %s)' % (
|
||||
self.id,
|
||||
self.amount,
|
||||
self.user.email,
|
||||
self.sent_to_customer,
|
||||
)
|
||||
|
||||
@property
|
||||
def vat(self):
|
||||
return Decimal(self.total*Decimal(0.2))
|
||||
|
||||
@property
|
||||
def filename(self):
|
||||
return 'bornhack_creditnote_%s.pdf' % self.pk
|
||||
|
||||
class Invoice(CreatedUpdatedModel):
|
||||
order = models.OneToOneField('shop.Order')
|
||||
pdf = models.FileField(null=True, blank=True, upload_to='invoices/')
|
||||
sent_to_customer = models.BooleanField(default=False)
|
||||
|
||||
def __str__(self):
|
||||
return 'invoice#%s - order %s - %s - total %s DKK (sent to customer: %s)' % (
|
||||
return 'invoice#%s - order %s - %s - total %s DKK (sent to %s: %s)' % (
|
||||
self.id,
|
||||
self.order.id,
|
||||
self.order.created,
|
||||
self.order.total,
|
||||
self.order.user.email,
|
||||
self.sent_to_customer,
|
||||
)
|
||||
|
||||
|
|
12
shop/templates/emails/creditnote_email.html
Normal file
12
shop/templates/emails/creditnote_email.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
Hello!<br>
|
||||
<br>
|
||||
This email contains your creditnote from BornHack.<br>
|
||||
The creditnote number is <b>{{ creditnote.pk }}</b>.<br>
|
||||
<br>
|
||||
The creditnote is attached in PDF format with the filename <b>{{ creditnote.filename }}</b>. The PDF contains the details about what this creditnote covers.<br>
|
||||
<br>
|
||||
<br>
|
||||
Best regards,<br>
|
||||
<br>
|
||||
The BornHack Team<br>
|
||||
<br>
|
14
shop/templates/emails/creditnote_email.txt
Normal file
14
shop/templates/emails/creditnote_email.txt
Normal file
|
@ -0,0 +1,14 @@
|
|||
Hello!
|
||||
|
||||
This email contains your creditnote from BornHack.
|
||||
The creditnote number is {{ creditnote.pk }}.
|
||||
|
||||
The creditnote is attached in PDF format with
|
||||
the filename {{ creditnote.filename }}. The PDF
|
||||
contains the details about what this creditnote
|
||||
covers.
|
||||
|
||||
|
||||
Best regards,
|
||||
|
||||
The BornHack Team
|
44
shop/templates/pdf/creditnote.html
Normal file
44
shop/templates/pdf/creditnote.html
Normal file
|
@ -0,0 +1,44 @@
|
|||
{% load static from staticfiles %}
|
||||
{% load shop_tags %}
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
|
||||
<table style="width:100%;">
|
||||
<tr>
|
||||
<td style="width: 75%;"> </td>
|
||||
<td>
|
||||
<h3>
|
||||
{{ creditnote.created|date:"b jS, Y" }}<br>
|
||||
Creditnote #{{ invoice.pk }}
|
||||
</h3>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Customer: {{ creditnote.order.user.email }}</h3>
|
||||
<br>
|
||||
<h2>CREDITNOTE</h2>
|
||||
<table style="width:90%; margin:1em;">
|
||||
<tr>
|
||||
<td>
|
||||
<b>Text
|
||||
<td>
|
||||
<b>Amount
|
||||
<tr>
|
||||
<td>
|
||||
{{ creditnote.text }}
|
||||
<td>
|
||||
{{ creditnote.amount|currency }}
|
||||
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<td>
|
||||
<strong>Danish VAT (25%)</strong>
|
||||
<td>
|
||||
{{ creditnote.vat|currency }}
|
||||
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<td>
|
||||
<strong>Total</strong>
|
||||
<td>
|
||||
{{ creditnote.amount|currency }}
|
||||
</table>
|
Loading…
Reference in a new issue