Fixed mailer smtp connection reuse

This commit is contained in:
Marc Aymerich 2015-07-02 10:49:44 +00:00
parent 120506229a
commit 3520b3968b
10 changed files with 215 additions and 24 deletions

View File

@ -434,5 +434,3 @@ serailzer self.instance on create.
* backendLog store method and language... and use it for display_script with correct lexer * backendLog store method and language... and use it for display_script with correct lexer
# process monitor data to represent state, or maybe create new resource datas when period expires? # process monitor data to represent state, or maybe create new resource datas when period expires?
# DNS when AAAA is specified include default A register?

View File

@ -228,7 +228,8 @@ def amend_bills(modeladmin, request, queryset):
} }
amend = Bill.objects.create( amend = Bill.objects.create(
account=bill.account, account=bill.account,
type=amend_type type=amend_type,
amend_of=bill,
) )
context['type'] = _(amend.get_type_display()) context['type'] = _(amend.get_type_display())
amend.comments = _("%(type)s of %(related_type)s %(number)s and creation date %(date)s") % context amend.comments = _("%(type)s of %(related_type)s %(number)s and creation date %(date)s") % context

View File

@ -22,9 +22,14 @@ from .models import Bill, Invoice, AmendmentInvoice, Fee, AmendmentFee, ProForma
PAYMENT_STATE_COLORS = { PAYMENT_STATE_COLORS = {
Bill.OPEN: 'grey',
Bill.CREATED: 'darkorange',
Bill.PROCESSED: 'darkorange',
Bill.AMENDED: 'blue',
Bill.PAID: 'green', Bill.PAID: 'green',
Bill.PENDING: 'darkorange', Bill.EXECUTED: 'darkorange',
Bill.BAD_DEBT: 'red', Bill.BAD_DEBT: 'red',
Bill.INCOMPLETE: 'red',
} }

View File

@ -96,10 +96,10 @@ class PaymentStateListFilter(SimpleListFilter):
if self.value() == 'OPEN': if self.value() == 'OPEN':
return queryset.filter(Q(is_open=True)|Q(type=queryset.model.PROFORMA)) return queryset.filter(Q(is_open=True)|Q(type=queryset.model.PROFORMA))
elif self.value() == 'PAID': elif self.value() == 'PAID':
zeros = queryset.filter(computed_total=0).values_list('id', flat=True) zeros = queryset.filter(computed_total=0, computed_total__isnull=True).values_list('id', flat=True)
ammounts = Transaction.objects.exclude(bill_id__in=zeros).secured().group_by('bill_id') ammounts = Transaction.objects.exclude(bill_id__in=zeros).secured().group_by('bill_id')
paid = [] paid = []
for bill_id, total in queryset.exclude(computed_total=0).values_list('id', 'computed_total'): for bill_id, total in queryset.exclude(computed_total=0, computed_total__isnull=True, is_open=True).values_list('id', 'computed_total'):
try: try:
ammount = sum([t.ammount for t in ammounts[bill_id]]) ammount = sum([t.ammount for t in ammounts[bill_id]])
except KeyError: except KeyError:
@ -107,13 +107,12 @@ class PaymentStateListFilter(SimpleListFilter):
else: else:
if abs(total) <= abs(ammount): if abs(total) <= abs(ammount):
paid.append(bill_id) paid.append(bill_id)
return queryset.filter(Q(computed_total=0)|Q(id__in=paid)) return queryset.filter(Q(computed_total=0)|Q(computed_total__isnull=True)|Q(id__in=paid)).exclude(is_open=True)
elif self.value() == 'PENDING': elif self.value() == 'PENDING':
has_transaction = queryset.exclude(transactions__isnull=True) has_transaction = queryset.exclude(transactions__isnull=True)
non_rejected = has_transaction.exclude(transactions__state=Transaction.REJECTED) non_rejected = has_transaction.exclude(transactions__state=Transaction.REJECTED)
non_rejected = non_rejected.values_list('id', flat=True).distinct() non_rejected = non_rejected.values_list('id', flat=True).distinct()
return queryset.filter(pk__in=non_rejected) return queryset.filter(pk__in=non_rejected)
elif self.value() == 'BAD_DEBT': elif self.value() == 'BAD_DEBT':
non_rejected = queryset.exclude(transactions__state=Transaction.REJECTED) closed = queryset.filter(is_open=False).exclude(computed_total=0)
non_rejected = non_rejected.values_list('id', flat=True).distinct() return closed.filter(Q(transactions__state=Transaction.REJECTED)|Q(transactions__isnull=True))
return queryset.exclude(pk__in=non_rejected)

File diff suppressed because one or more lines are too long

View File

@ -64,15 +64,17 @@ class Bill(models.Model):
PROCESSED = 'PROCESSED' PROCESSED = 'PROCESSED'
AMENDED = 'AMENDED' AMENDED = 'AMENDED'
PAID = 'PAID' PAID = 'PAID'
PENDING = 'PENDING' EXECUTED = 'EXECUTED'
BAD_DEBT = 'BAD_DEBT' BAD_DEBT = 'BAD_DEBT'
INCOMPLETE = 'INCOMPLETE'
PAYMENT_STATES = ( PAYMENT_STATES = (
(OPEN, _("Open")), (OPEN, _("Open")),
(CREATED, _("Created")), (CREATED, _("Created")),
(PROCESSED, _("Processed")), (PROCESSED, _("Processed")),
(AMENDED, _("Amended")), (AMENDED, _("Amended")),
(PAID, _("Paid")), (PAID, _("Paid")),
(PENDING, _("Pending")), (INCOMPLETE, _('Incomplete')),
(EXECUTED, _("Executed")),
(BAD_DEBT, _("Bad debt")), (BAD_DEBT, _("Bad debt")),
) )
BILL = 'BILL' BILL = 'BILL'
@ -92,7 +94,8 @@ class Bill(models.Model):
number = models.CharField(_("number"), max_length=16, unique=True, blank=True) number = models.CharField(_("number"), max_length=16, unique=True, blank=True)
account = models.ForeignKey('accounts.Account', verbose_name=_("account"), account = models.ForeignKey('accounts.Account', verbose_name=_("account"),
related_name='%(class)s') related_name='%(class)s')
# amend_of = models.ForeignKey('self', null=True, blank=True, verbose_name=_("amend of"), related_name='amends') amend_of = models.ForeignKey('self', null=True, blank=True, verbose_name=_("amend of"),
related_name='amends')
type = models.CharField(_("type"), max_length=16, choices=TYPES) type = models.CharField(_("type"), max_length=16, choices=TYPES)
created_on = models.DateField(_("created on"), auto_now_add=True) created_on = models.DateField(_("created on"), auto_now_add=True)
closed_on = models.DateField(_("closed on"), blank=True, null=True) closed_on = models.DateField(_("closed on"), blank=True, null=True)
@ -133,14 +136,49 @@ class Bill(models.Model):
def payment_state(self): def payment_state(self):
if self.is_open or self.get_type() == self.PROFORMA: if self.is_open or self.get_type() == self.PROFORMA:
return self.OPEN return self.OPEN
# elif self.amends.filter(is_open=False).exists(): elif self.amends.filter(is_open=False).exists():
# return self.AMENDED return self.AMENDED
# TODO optimize this with a single query secured = 0
secured = self.transactions.secured().amount() or 0 pending = 0
if abs(secured) >= abs(self.get_total()): created = False
processed = False
executed = False
rejected = False
for transaction in self.transactions.all():
if transaction.state == transaction.SECURED:
secured += transaction.amount
pending += transaction.amount
elif transaction.state == transaction.WAITTING_PROCESSING:
pending += transaction.amount
created = True
elif transaction.state == transaction.WAITTING_EXECUTION:
pending += transaction.amount
processed = True
elif transaction.state == transaction.EXECUTED:
pending += transaction.amount
executed = True
elif transaction.state == transaction.REJECTED:
rejected = True
else:
raise TypeError("Unknown state")
ongoing = bool(secured != 0 or created or processed or executed)
total = self.get_total()
if total >= 0:
if secured >= total:
return self.PAID return self.PAID
elif self.transactions.exclude_rejected().exists(): elif ongoing and pending < total:
return self.PENDING return self.INCOMPLETE
else:
if secured <= total:
return self.PAID
elif ongoing and pending > total:
return self.INCOMPLETE
if created:
return self.CREATED
elif processed:
return self.PROCESSED
elif executed:
return self.EXECUTED
return self.BAD_DEBT return self.BAD_DEBT
def get_total(self): def get_total(self):

View File

@ -172,13 +172,14 @@ class Domain(models.Model):
type=Record.MX, type=Record.MX,
value=mx value=mx
)) ))
if not has_a and not has_aaaa: if not has_a:
default_a = settings.DOMAINS_DEFAULT_A default_a = settings.DOMAINS_DEFAULT_A
if default_a: if default_a:
records.append(AttrDict( records.append(AttrDict(
type=Record.A, type=Record.A,
value=default_a value=default_a
)) ))
if not has_aaaa:
default_aaaa = settings.DOMAINS_DEFAULT_AAAA default_aaaa = settings.DOMAINS_DEFAULT_AAAA
if default_aaaa: if default_aaaa:
records.append(AttrDict( records.append(AttrDict(

View File

@ -25,7 +25,8 @@ def send_message(message, num=0, connection=None, bulk=settings.MAILER_BULK_MESS
error = None error = None
try: try:
connection.connection.sendmail(message.from_address, [message.to_address], smart_str(message.content)) connection.connection.sendmail(message.from_address, [message.to_address], smart_str(message.content))
except (SocketError, smtplib.SMTPSenderRefused, except (SocketError,
smtplib.SMTPSenderRefused,
smtplib.SMTPRecipientsRefused, smtplib.SMTPRecipientsRefused,
smtplib.SMTPAuthenticationError) as err: smtplib.SMTPAuthenticationError) as err:
message.defer() message.defer()
@ -33,6 +34,7 @@ def send_message(message, num=0, connection=None, bulk=settings.MAILER_BULK_MESS
else: else:
message.sent() message.sent()
message.log(error) message.log(error)
return connection
def send_pending(bulk=settings.MAILER_BULK_MESSAGES): def send_pending(bulk=settings.MAILER_BULK_MESSAGES):
@ -41,7 +43,7 @@ def send_pending(bulk=settings.MAILER_BULK_MESSAGES):
connection = None connection = None
num = 0 num = 0
for message in Message.objects.filter(state=Message.QUEUED).order_by('priority'): for message in Message.objects.filter(state=Message.QUEUED).order_by('priority'):
send_message(message, num, connection, bulk) connection = send_message(message, num, connection, bulk)
num += 1 num += 1
now = timezone.now() now = timezone.now()
qs = Q() qs = Q()

View File

@ -0,0 +1,62 @@
.highlight .hll { background-color: #ffffcc }
.highlight { background: #f8f8f8; }
.highlight .c { color: #408080; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #FF0000 } /* Error */
.highlight .k { color: #008000; font-weight: bold } /* Keyword */
.highlight .o { color: #666666 } /* Operator */
.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #BC7A00 } /* Comment.Preproc */
.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */
.highlight .cs { color: #408080; font-style: italic } /* Comment.Special */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
.highlight .go { color: #808080 } /* Generic.Output */
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0040D0 } /* Generic.Traceback */
.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008000 } /* Keyword.Pseudo */
.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #B00040 } /* Keyword.Type */
.highlight .m { color: #666666 } /* Literal.Number */
.highlight .s { color: #BA2121 } /* Literal.String */
.highlight .na { color: #7D9029 } /* Name.Attribute */
.highlight .nb { color: #008000 } /* Name.Builtin */
.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
.highlight .no { color: #880000 } /* Name.Constant */
.highlight .nd { color: #AA22FF } /* Name.Decorator */
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0000FF } /* Name.Function */
.highlight .nl { color: #A0A000 } /* Name.Label */
.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #19177C } /* Name.Variable */
.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #666666 } /* Literal.Number.Float */
.highlight .mh { color: #666666 } /* Literal.Number.Hex */
.highlight .mi { color: #666666 } /* Literal.Number.Integer */
.highlight .mo { color: #666666 } /* Literal.Number.Oct */
.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
.highlight .sc { color: #BA2121 } /* Literal.String.Char */
.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #BA2121 } /* Literal.String.Double */
.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.highlight .sx { color: #008000 } /* Literal.String.Other */
.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
.highlight .s1 { color: #BA2121 } /* Literal.String.Single */
.highlight .ss { color: #19177C } /* Literal.String.Symbol */
.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
.highlight .vc { color: #19177C } /* Name.Variable.Class */
.highlight .vg { color: #19177C } /* Name.Variable.Global */
.highlight .vi { color: #19177C } /* Name.Variable.Instance */
.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */

View File

@ -0,0 +1,61 @@
.hll { background-color: #ffffcc }
.c { color: #999988; font-style: italic } /* Comment */
.err { color: #a61717; background-color: #e3d2d2 } /* Error */
.k { color: #000000; font-weight: bold } /* Keyword */
.o { color: #000000; font-weight: bold } /* Operator */
.cm { color: #999988; font-style: italic } /* Comment.Multiline */
.cp { color: #999999; font-weight: bold; font-style: italic } /* Comment.Preproc */
.c1 { color: #999988; font-style: italic } /* Comment.Single */
.cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
.gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.ge { color: #000000; font-style: italic } /* Generic.Emph */
.gr { color: #aa0000 } /* Generic.Error */
.gh { color: #999999 } /* Generic.Heading */
.gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.go { color: #888888 } /* Generic.Output */
.gp { color: #555555 } /* Generic.Prompt */
.gs { font-weight: bold } /* Generic.Strong */
.gu { color: #aaaaaa } /* Generic.Subheading */
.gt { color: #aa0000 } /* Generic.Traceback */
.kc { color: #000000; font-weight: bold } /* Keyword.Constant */
.kd { color: #000000; font-weight: bold } /* Keyword.Declaration */
.kn { color: #000000; font-weight: bold } /* Keyword.Namespace */
.kp { color: #000000; font-weight: bold } /* Keyword.Pseudo */
.kr { color: #000000; font-weight: bold } /* Keyword.Reserved */
.kt { color: #445588; font-weight: bold } /* Keyword.Type */
.m { color: #009999 } /* Literal.Number */
.s { color: #d01040 } /* Literal.String */
.na { color: #008080 } /* Name.Attribute */
.nb { color: #0086B3 } /* Name.Builtin */
.nc { color: #445588; font-weight: bold } /* Name.Class */
.no { color: #008080 } /* Name.Constant */
.nd { color: #3c5d5d; font-weight: bold } /* Name.Decorator */
.ni { color: #800080 } /* Name.Entity */
.ne { color: #990000; font-weight: bold } /* Name.Exception */
.nf { color: #990000; font-weight: bold } /* Name.Function */
.nl { color: #990000; font-weight: bold } /* Name.Label */
.nn { color: #555555 } /* Name.Namespace */
.nt { color: #000080 } /* Name.Tag */
.nv { color: #008080 } /* Name.Variable */
.ow { color: #000000; font-weight: bold } /* Operator.Word */
.w { color: #bbbbbb } /* Text.Whitespace */
.mf { color: #009999 } /* Literal.Number.Float */
.mh { color: #009999 } /* Literal.Number.Hex */
.mi { color: #009999 } /* Literal.Number.Integer */
.mo { color: #009999 } /* Literal.Number.Oct */
.sb { color: #d01040 } /* Literal.String.Backtick */
.sc { color: #d01040 } /* Literal.String.Char */
.sd { color: #d01040 } /* Literal.String.Doc */
.s2 { color: #d01040 } /* Literal.String.Double */
.se { color: #d01040 } /* Literal.String.Escape */
.sh { color: #d01040 } /* Literal.String.Heredoc */
.si { color: #d01040 } /* Literal.String.Interpol */
.sx { color: #d01040 } /* Literal.String.Other */
.sr { color: #009926 } /* Literal.String.Regex */
.s1 { color: #d01040 } /* Literal.String.Single */
.ss { color: #990073 } /* Literal.String.Symbol */
.bp { color: #999999 } /* Name.Builtin.Pseudo */
.vc { color: #008080 } /* Name.Variable.Class */
.vg { color: #008080 } /* Name.Variable.Global */
.vi { color: #008080 } /* Name.Variable.Instance */
.il { color: #009999 } /* Literal.Number.Integer.Long */