Skip to content

Commit

Permalink
Merge branch 'master' into 1.7
Browse files Browse the repository at this point in the history
  • Loading branch information
jsayles committed Dec 29, 2016
2 parents 54df6f7 + d02a231 commit a91037a
Show file tree
Hide file tree
Showing 14 changed files with 187 additions and 79 deletions.
7 changes: 7 additions & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# This is the official list of Nadine authors for copywrite purposes.
# This file is distinct from the CONTRIBUTORS files.
# See the latter for an explanation.

Office Nomads - http://officenomads.com
Jacob Sayles - https://github.com/jsayles/

18 changes: 18 additions & 0 deletions CONTRIBUTORS
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# People who have contributed Nadine code.
# The AUTHORS file lists the copyright holders

Office Nomads - http://officenomads.com
Vancity Community Foundation - http://vancitycommunityfoundation.ca

Jacob Sayles - https://github.com/jsayles/
Trevor F. Smith - https://github.com/TrevorFSmith
Paul Watts - https://github.com/paulcwatts
Griffin Wesler - https://github.com/rasselbock
Paul Laskowski - http://warmbowski.org
Alice Wicks - http://alicewicks.com
Mike McCracken - https://github.com/loneconspirator
Alexandra Southwell - https://github.com/abkruse




File renamed without changes.
9 changes: 7 additions & 2 deletions comlink/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from django.contrib.auth.models import User
from django.utils.datastructures import MultiValueDict
from django.utils.translation import ugettext as _
from django.core.urlresolvers import reverse
from django.contrib.sites.models import Site

from email.Utils import parseaddr

Expand Down Expand Up @@ -88,6 +90,9 @@ def references(self):
def in_reply_to(self):
return self.headers.get('In-Reply-To', None)

@property
def site_url(self): return 'https://%s%s' % (Site.objects.get_current().domain, reverse('comlink_mail', kwargs={'id': self.id}))

def get_mailgun_data(self, stripped=True, footer=True):
if stripped:
body_plain = self.stripped_text
Expand All @@ -98,10 +103,10 @@ def get_mailgun_data(self, stripped=True, footer=True):

if footer:
# Add in a footer
text_footer = "\n\n-------------------------------------------\n*~*~*~* Sent through Nadine *~*~*~* "
text_footer = "\n\n-------------------------------------------\n*~*~*~* Sent through Nadine *~*~*~*\n%s" % self.site_url
body_plain = body_plain + text_footer
if body_html:
html_footer = "<br><br>-------------------------------------------<br>*~*~*~* Sent through Nadine *~*~*~* "
html_footer = "<br><br>-------------------------------------------<br>*~*~*~* Sent through Nadine *~*~*~*\n%s" % self.site_url
body_html = body_html + html_footer

# Build and return our data
Expand Down
6 changes: 5 additions & 1 deletion nadine/models/payment.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,12 @@ class Bill(models.Model):
new_member_deposit = models.BooleanField(default=False, blank=False, null=False)
paid_by = models.ForeignKey(User, blank=True, null=True, related_name='guest_bills')

@property
def overage_days(self):
return self.dropins.count() - self.membership.dropin_allowance
days = self.dropins.count() + self.guest_dropins.count()
if self.membership and self.membership.dropin_allowance < days:
return days - self.membership.dropin_allowance
return 0

class Meta:
app_label = 'nadine'
Expand Down
76 changes: 35 additions & 41 deletions nadine/utils/mailgun.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import datetime
import logging
import email.utils
from collections import OrderedDict

from django.conf import settings
from django.contrib.auth.models import User
Expand All @@ -23,53 +24,46 @@ class MailgunException(Exception):
pass


def address_map(mailgun_data, key, exclude=None):
if not exclude: exclude = []
a_map = OrderedDict()
if key in mailgun_data:
for a in mailgun_data[key]:
name, address = email.utils.parseaddr(a)
if not address in exclude:
a_map[address.lower()] = a
# print("mailgun_data[%s] = %s" % (key, mailgun_data[key]))
# print("exclude = %s" % exclude)
# print("a_map = %s" % a_map)
return a_map


def clean_mailgun_data(mailgun_data):
# Make sure we have what we need
from_name, from_address = email.utils.parseaddr(mailgun_data["from"])
to_name, to_address = email.utils.parseaddr(mailgun_data["to"][0])
subject = mailgun_data["subject"]
if not from_address or not to_address or not subject:
if not 'to' in mailgun_data or not 'from' in mailgun_data or not 'subject' in mailgun_data:
raise MailgunException("Mailgun data missing FROM, TO, or SUBJECT!")
logger.debug("from: %s, to: %s, subject: %s" % (from_address, to_address, subject))
logger.debug("dirty mailgun_data: %s" % mailgun_data)

# Clean up our bcc list
bcc_list = None
if "bcc" in mailgun_data:
bcc_list = mailgun_data["bcc"]
if from_address in bcc_list:
bcc_list.remove(from_address)
if to_address in bcc_list:
bcc_list.remove(to_address)
mailgun_data["bcc"] = list(set(bcc_list))
logger.debug("bcc: %s" % mailgun_data["bcc"])

# Clean up our cc list too
cc_list = None
if "cc" in mailgun_data:
cc_list = mailgun_data["cc"]
if from_address in cc_list:
cc_list.remove(from_address)
if to_address in cc_list:
cc_list.remove(to_address)
if bcc_list:
for cc in cc_list:
if cc in bcc_list:
cc_list.remove(cc)
mailgun_data["cc"] = list(set(cc_list))
logger.debug("cc: %s" % mailgun_data["cc"])
# Compile all our addresses
from_name, from_address = email.utils.parseaddr(mailgun_data["from"])
to_name, to_address = email.utils.parseaddr(mailgun_data["to"][0])
exclude = [from_address, to_address]
bccs = address_map(mailgun_data, "bcc", exclude)
exclude.extend(bccs.keys())
# We do not want to remove our first 'to' address
to_exclude = list(set(exclude))
to_exclude.remove(to_address)
tos = address_map(mailgun_data, "to", to_exclude)
exclude.extend(tos.keys())
ccs = address_map(mailgun_data, "cc", exclude)

# Lastly clean up our to list
to_list = mailgun_data["to"]
if len(to_list) > 1:
if from_address in to_list:
to_list.remove(from_address)
for to in to_list[1:]:
if cc_list and to in cc_list:
to_list.remove(to)
if bcc_list and to in bcc_list:
to_list.remove(to)
mailgun_data["to"] = to_list
# Repopulate our data with our clean lists
mailgun_data["bcc"] = bccs.values()
mailgun_data["cc"] = ccs.values()
mailgun_data["to"] = tos.values()

logger.debug("clean mailgun_data: %s" % mailgun_data)
return mailgun_data

def inject_list_headers(mailgun_data):
# Attach some headers: LIST-ID, REPLY-TO, Precedence...
Expand Down
43 changes: 43 additions & 0 deletions nadine/utils/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,49 @@
from django.conf import settings

from suds.client import Client
import mailgun

class MailgunTestCase(SimpleTestCase):
bob_email = "bob@bob.net"
bob = "Bob Smith <%s>" % bob_email
alice_email = "alice@312main.ca"
alice = "Alice Smith <%s>" % alice_email
frank_email = "frank@example.com"
frank = "Frank Smith <%s>" % frank_email
mailgun_data = {'from':bob,
'subject': "This is a test",
'to':[alice, frank, bob],
'cc':[frank, alice, bob],
'bcc':[bob, alice, frank],
}

def test_address_map(self):
addresses = mailgun.address_map(self.mailgun_data, 'BUNK', [])
self.assertEquals(addresses, {})

exclude = []
addresses = mailgun.address_map(self.mailgun_data, 'to', exclude)
self.assertEqual(len(addresses), 3)
self.assertEqual(self.alice_email, addresses.keys()[0], exclude)
self.assertEqual(self.bob_email, addresses.keys()[2], exclude)

exclude = [self.bob_email]
addresses = mailgun.address_map(self.mailgun_data, 'to', exclude)
self.assertEqual(len(addresses), 2)
self.assertEqual(self.alice_email, addresses.keys()[0], exclude)

def test_clean_mailgun_data(self):
clean_data = mailgun.clean_mailgun_data(self.mailgun_data)
# print clean_data
tos = clean_data['to']
self.assertEqual(len(tos), 1)
self.assertEqual(tos[0], self.alice)
ccs = clean_data['cc']
self.assertEqual(len(ccs), 0)
bccs = clean_data['bcc']
self.assertEqual(len(bccs), 1)
self.assertEqual(bccs[0], self.frank)


class UsaepayTestCase(SimpleTestCase):
_client = None
Expand Down
7 changes: 0 additions & 7 deletions staff/templates/staff/activity_date.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,11 @@

{% block sub-title %}Activity on {{ activity_date|date:"M d, Y" }} | {% endblock %}

{% block sub-head %}
<link rel="stylesheet" href="{% static 'css/jquery-ui.min.css' %}" />
<script src="{% static 'jquery-3.1.1.min.js' %}"></script>
<script src="{% static 'jquery-ui.min.js' %}"></script>
{% endblock %}

{% block style%}
nav #activity-tab { background: #FBD850; color: black; }
#content table { width: 100%; }
.log-note { width: 100px; }
#quick-links { text-align: right; margin-bottom: 20px;}

{% endblock %}

{% block content %}
Expand Down
5 changes: 5 additions & 0 deletions staff/templates/staff/bills.html
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ <h4>
Deposit: ${{ bill.new_member_deposit }}
</div>
{% endif %}
{% if bill.overage_days %}
<div class="bill-info">
Overage: {{ bill.overage_days }} day{{ bill.overage_days|pluralize }}
</div>
{% endif %}
{% if bill.dropins.all %}
<div class="bill-info">Dropins ({{ bill.dropins.count }}):
{% for dropin in bill.dropins.all %}
Expand Down
19 changes: 18 additions & 1 deletion staff/templates/staff/charges.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ <h2>
Daily Charges - {{ date|date:"l, M dS" }}
<span style="float:right;">
<a href="{% url 'staff_charges' previous_date.year previous_date.month previous_date.day %}">&larr;</a>
<a href="{% url 'staff_charges_today' %}">&bull;</a>
<!-- <a href="{% url 'staff_charges_today' %}">&bull;</a> -->
<input type='date' name='date' class='datepicker' value="{{ date|date:'Y-m-d' }}" style='font-size:.6em; text-align:center; width:150px;'/>
<a href="{% url 'staff_charges' next_date.year next_date.month next_date.day %}">&rarr;</a>
</span>
</h2>
Expand Down Expand Up @@ -121,3 +122,19 @@ <h3>Other Transactions</h3>
{% endif %}

{% endblock %}

{% block extrajs %}
<script>
(function() {
$('.datepicker').datepicker({
dateFormat: 'yy-mm-dd',
onSelect: function(ui, e) {
var date = ui.split('-');
var url = "{% url 'staff_charges' 2016 12 14 %}".replace(/14/, date[2]).replace(/12/, date[1]).replace(/2016/, date[0]);

window.location.href = url;
}
});
})();
</script>
{% endblock %}
22 changes: 22 additions & 0 deletions staff/templates/staff/security_deposit_table.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<table>
<tr>
<th>Name</th>
<th>Amount</th>
<th>Action</th>
<th></th>
</tr>
{% for d in deposits %}
<tr class="{% cycle 'row-even' 'row-odd' %}">
<td nowrap ><a href="{% url 'staff_user_detail' d.username %}">{{ d.name }}</a></td>
<td>${{ d.amount }}</td>
<td>
<form action="." method="POST" onSubmit="return confirm('Are you sure?');">
<input name="deposit_id" value="{{ d.deposit_id }}" type="hidden" />
<input name="mark_returned" type="submit" Value="Mark Returned" />
{% csrf_token %}
</form>
</td>
<td></td>
</tr>
{% endfor %}
</table>
38 changes: 15 additions & 23 deletions staff/templates/staff/security_deposits.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,21 @@
{% include "staff/member_menu.frag" %}

<h2>Security Deposits</h2>
<table>
<tr>
<th>Name</th>
<th>Amount</th>
<th>Action</th>
<th></th>
</tr>
{% for d in deposits %}
<tr class="{% cycle 'row-even' 'row-odd' %}">
<td nowrap ><a href="{% url 'staff_user_detail' d.username %}">{{ d.name }}</a></td>
<td>${{ d.amount }}</td>
<td>
<form action="." method="POST" onSubmit="return confirm('Are you sure?');">
<input name="deposit_id" value="{{ d.deposit_id }}" type="hidden" />
<input name="mark_returned" type="submit" Value="Mark Returned" />
{% csrf_token %}
</form>
</td>
<td></td>
</tr>
{% endfor %}
<tr><th><strong>Total Deposits</strong><th align="left">${{total_deposits}}</th></tr>
</table>
<strong>Total Deposits: </strong> ${{total_deposits}}

{% if inactive_deposits %}
<h3>Inactive Members</h3>
{% with inactive_deposits as deposits %}
{% include "staff/security_deposit_table.html" %}
{% endwith %}
{% endif %}

{% if active_deposits %}
<h3>Active Members</h3>
{% with active_deposits as deposits %}
{% include "staff/security_deposit_table.html" %}
{% endwith %}
{% endif %}


{% endblock %}
2 changes: 1 addition & 1 deletion staff/tests/test_billing.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ def test_drop_in_on_billing_date_is_associated_with_correct_bill(self):
self.assertEqual(may_20_overage.membership.membership_plan, self.pt5Plan)
self.assertEqual(date(2010, 6, 19), may_20_overage.bill_date)
self.assertEqual(9, may_20_overage.dropins.count())
self.assertEqual(4, may_20_overage.overage_days())
self.assertEqual(4, may_20_overage.overage_days)
self.assertEqual(80, may_20_overage.amount)

# Third bill is for the new Basic membership
Expand Down
14 changes: 11 additions & 3 deletions staff/views/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,20 @@ def security_deposits(request):
if username:
return HttpResponseRedirect(reverse('staff_user_detail', kwargs={'username': username}))

deposits = []
active_deposits = []
inactive_deposits = []
total_deposits = 0
for deposit in SecurityDeposit.objects.filter(returned_date=None).order_by('user__username'):
deposits.append({'username': deposit.user.username, 'name': deposit.user.get_full_name(), 'deposit_id': deposit.id, 'amount': deposit.amount})
d = {'username': deposit.user.username, 'name': deposit.user.get_full_name(), 'deposit_id': deposit.id, 'amount': deposit.amount}
if deposit.user.profile.is_active():
active_deposits.append(d)
else:
inactive_deposits.append(d)
total_deposits = total_deposits + deposit.amount
context = {'deposits': deposits, 'total_deposits': total_deposits}
context = {'active_deposits': active_deposits,
'inactive_deposits':inactive_deposits,
'total_deposits': total_deposits
}
return render(request, 'staff/security_deposits.html', context)


Expand Down

0 comments on commit a91037a

Please sign in to comment.