Skip to content
Browse files

add configurable rules for where to send report emails.

  • Loading branch information...
1 parent 0c63d4e commit b4727ae9a1dbeab31f831d30ceeedb9253eee3f4 @visiblegovernment committed Feb 1, 2010
View
7 README
@@ -1,8 +1,9 @@
This is the code for http://fixmystreet.ca.
-You can find developer documentation here:
+Official installation instructions are available here:
+ http://wiki.github.com/visiblegovernment/django-fixmystreet/
+A first-hand account of an installation on ms-dos using a VMware Virtual Machine is here:
https://www.socialtext.net/lukec/index.cgi?howto_set_up_fixmystreet_ca_developer_environment
-
-FixMyStreet is created for http://visiblegovernment.ca/
+FixMyStreet was created for http://visiblegovernment.ca/.
View
6 mainapp/admin.py
@@ -1,7 +1,10 @@
-from fixmystreet.mainapp.models import Ward,ReportCategory, ReportCategoryClass, FaqEntry, Councillor
+from fixmystreet.mainapp.models import EmailRule,Ward,ReportCategory,City, ReportCategoryClass, FaqEntry, Councillor
from django.contrib import admin
from contrib.transmeta import canonical_fieldname
+admin.site.register(EmailRule)
+admin.site.register(City)
+
class ReportCategoryClassAdmin(admin.ModelAdmin):
list_display = ('name',)
@@ -14,7 +17,6 @@ class ReportCategoryAdmin(admin.ModelAdmin):
class FaqEntryAdmin(admin.ModelAdmin):
list_display = ('q', 'order')
-# prepopulated_fields = {'slug': ('q') }
admin.site.register(FaqEntry, FaqEntryAdmin)
View
1 mainapp/fixtures/initial_data.json
@@ -20,7 +20,6 @@
"pk": 1,
"model": "mainapp.city",
"fields": {
- "geom": null,
"name": "Oglo",
"province": 1,
"email": "example_city_email@yahoo.ca"
View
96 mainapp/models.py
@@ -9,6 +9,7 @@
import md5
import urllib
import time
+from mainapp import emailrules
from datetime import datetime as dt
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy, ugettext as _
@@ -30,15 +31,12 @@ class City(models.Model):
name = models.CharField(max_length=100)
# the city's 311 email, if it has one.
email = models.EmailField(blank=True, null=True)
- # unused, for now.
- geom = models.PolygonField( null=True)
objects = models.GeoManager()
def __unicode__(self):
return self.name
-
-
+
def get_absolute_url(self):
return settings.SITE_URL + "/cities/" + str(self.id)
@@ -68,6 +66,21 @@ class Ward(models.Model):
def get_absolute_url(self):
return settings.SITE_URL + "/wards/" + str(self.id)
+ # return a list of email addresses to send new problems in this ward to.
+ def get_emails(self,report):
+ emails = []
+ if self.city.email:
+ emails.append(self.city.email)
+
+ # check for rules for this city.
+ rules = EmailRule.objects.filter(city=self.city)
+ for rule in rules:
+ rule_email = rule.get_email(report)
+ if rule_email:
+ emails.append(rule_email)
+ return( emails )
+
+
class Meta:
db_table = u'wards'
@@ -93,7 +106,54 @@ class ReportCategory(models.Model):
class Meta:
db_table = u'report_categories'
translate = ('name', 'hint', )
-
+
+
+# Override where to send a report for a given city.
+#
+# If no rule exists, the email destination is the 311 email address
+# for that city.
+#
+# Cities can have more than one rule. If a given report matches more than
+# one rule, more than one email is sent. (Desired behaviour for cities that
+# want councillors CC'd)
+
+class EmailRule(models.Model):
+ TO_COUNCILLOR = 0
+ MATCHING_CATEGORY_CLASS = 1
+ NOT_MATCHING_CATEGORY_CLASS = 2
+
+ RuleChoices = [
+ (TO_COUNCILLOR, 'Send Reports to Councillor Email Address'),
+ (MATCHING_CATEGORY_CLASS, 'Send Reports Matching Category Class (eg. Parks) To This Email'),
+ (NOT_MATCHING_CATEGORY_CLASS, 'Send Reports Not Matching Category Class To This Email'), ]
+
+ RuleBehavior = { TO_COUNCILLOR: emailrules.ToCouncillor,
+ MATCHING_CATEGORY_CLASS: emailrules.MatchingCategoryClass,
+ NOT_MATCHING_CATEGORY_CLASS: emailrules.NotMatchingCategoryClass }
+
+ rule = models.IntegerField(choices=RuleChoices)
+
+ # the city this rule applies to
+ city = models.ForeignKey(City)
+
+ # filled in if this is a category class rule
+ category_class = models.ForeignKey(ReportCategoryClass,null=True, blank=True)
+
+ # filled in if this is a category rule
+ category = models.ForeignKey(ReportCategory,null=True, blank=True)
+
+ # filled in if an additional email address is required for the rule type
+ email = models.EmailField(blank=True, null=True)
+
+ def get_email(self,report):
+ rule_behavior = EmailRule.RuleBehavior[ self.rule ]()
+ return( rule_behavior.get_email(report,self))
+
+ def __str__(self):
+ rule_behavior = EmailRule.RuleBehavior[ self.rule ]()
+ return( self.city.name + ": " + rule_behavior.describe(self) )
+
+
class Report(models.Model):
title = models.CharField(max_length=100, verbose_name = ugettext_lazy("Subject"))
category = models.ForeignKey(ReportCategory,null=True)
@@ -183,21 +243,23 @@ def notify_on_new(self):
subject = render_to_string("emails/send_report_to_city/subject.txt", {'update': self })
message = render_to_string("emails/send_report_to_city/message.txt", { 'update': self })
- if self.report.ward.city.email:
- email_addr = self.report.ward.city.email
- else:
- email_addr = self.report.ward.councillor.email
-
+ to_email_addrs = self.report.ward.get_emails(self.report)
email_msg = EmailMessage(subject,message,settings.EMAIL_FROM_USER,
- [email_addr], headers = {'Reply-To': self.email })
+ to_email_addrs, headers = {'Reply-To': self.email })
if self.report.photo:
email_msg.attach_file( self.report.photo.file.name )
email_msg.send()
# update report to show time sent to city.
self.report.sent_at=dt.now()
- self.report.email_sent_to = email_addr
+ email_addr_str = ""
+ for email in to_email_addrs:
+ if email_addr_str != "":
+ email_addr_str += ", "
+ email_addr_str += email
+
+ self.report.email_sent_to = email_addr_str
self.report.save()
@@ -344,11 +406,13 @@ class CityMap(GoogleMap):
def __init__(self,city):
polygons = []
+ kml_url = 'http://localhost:8000/media/kml/' + city.name + '.kml'
- for ward in Ward.objects.filter(city=city):
- for poly in ward.geom:
- polygons.append( GPolygon( poly ) )
- GoogleMap.__init__(self,zoom=13,key=settings.GMAP_KEY, polygons=polygons, dom_id='map_canvas')
+ ward = Ward.objects.filter(city=city)[:1][0]
+ #for ward in Ward.objects.filter(city=city):
+ # for poly in ward.geom:
+ # polygons.append( GPolygon( poly ) )
+ GoogleMap.__init__(self,center=ward.geom.centroid,zoom=13,key=settings.GMAP_KEY, polygons=polygons, kml_urls=[kml_url],dom_id='map_canvas')
View
5 settings.py
@@ -3,7 +3,8 @@
import logging
PROJECT_PATH = os.path.abspath(os.path.dirname(__file__))
-
+TEST_RUNNER='django.contrib.gis.tests.run_tests'
+POSTGIS_TEMPLATE = 'template_postgis'
logging.basicConfig(
level = logging.DEBUG,
@@ -45,7 +46,7 @@
# http://docs.djangoproject.com/en/dev/ref/settings/#file-upload-permissions
FILE_UPLOAD_PERMISSIONS = 0644
-
+DATE_FORMAT = "l, F jS, Y"
# List of callables that know how to import templates from various sources.
TEMPLATE_LOADERS = (
View
2 templates/about.html
@@ -26,7 +26,7 @@
{% trans "In addition, Chris Taggart would like to thank:" %}
</p>
<ul>
- <li>{% trans "Pierre Lewis, for his MTM conversion script. The script enabled conversion from the City's MTM projection to the Google-friendly WGS-84 format." %}
+ <li>{% trans "Pierre Lewis, for his MTM conversion script. The script enabled conversion from Ottawa's MTM projection to the Google-friendly WGS-84 format." %}
</ul>
</div>
</div>
View
2 templates/contact/new.html
@@ -8,7 +8,7 @@
{% blocktrans %}
<p>
Please <strong>DO NOT</strong> report problems through this form.
- Messages go to the team behind FixMyStreet.ca, not to City Councillors.
+ Messages go to the team behind FixMyStreet.ca, not to city councillors.
</p>
<p>
To report a problem, please follow the instructions <a href="/">here</a>.
View
10 templates/emails/confirm/message.txt
@@ -1,11 +1,7 @@
-{% if update.author %}
-Hello {{update.author}}
-{% endif %}
+{% if update.author %}Hello {{update.author|safe}}{% endif %}
-{% if update.first_update %}
-Thank you for submitting the report '{{update.report.title}}' to FixMyStreet.ca.
-{% else %}
-Thank you for submitting an update on the report '{{update.report.title}}'
+{% if update.first_update %}Thank you for submitting the report '{{update.report.title|safe}}' to FixMyStreet.ca.
+{% else %}Thank you for submitting an update on the report '{{update.report.title|safe}}'
to FixMyStreet.ca.
{% endif %}
View
2 templates/emails/confirm/subject.txt
@@ -1 +1 @@
-FixMyStreet.ca - Please Confirm {% if update.first_update %}Report{% else %}Update For{% endif %}: {{update.report.title}}
+FixMyStreet.ca - Please Confirm {% if update.first_update %}Report{% else %}Update For{% endif %}: {{update.report.title|safe}}
View
2 templates/emails/contact/message.txt
@@ -1,4 +1,4 @@
From: {{name}} ({{email}})
------------------------------------------------------------
-{{body}}
+{{body|safe}}
------------------------------------------------------------
View
6 templates/emails/report_update/message.txt
@@ -1,10 +1,10 @@
-The FixMyStreet.ca Report: '{{update.report.title}}'
-was updated by {{update.author}} on {{update.created_at}}:
+The FixMyStreet.ca Report: '{{update.report.title|safe}}'
+was updated by {{update.author|safe}} on {{update.created_at|date}}:
{% if update.is_fixed %}This issue has been fixed. {% endif %}
-----------------------------------------------------------------------------
-{{update.desc}}
+{{update.desc|safe}}
-----------------------------------------------------------------------------
View
2 templates/emails/report_update/subject.txt
@@ -1 +1 @@
-FixMyStreet.ca: '{{update.report.title}}' {% if update.is_fixed %} Fixed {% else %} Updated {% endif %}
+FixMyStreet.ca: '{{update.report.title|safe}}' {% if update.is_fixed %} Fixed {% else %} Updated {% endif %}
View
15 templates/emails/send_report_to_city/message.txt
@@ -1,10 +1,11 @@
-Title: {{update.report.title}}
-Category: {{update.report.category.name}}
-Phone: {{update.phone}}
-Email: {{update.email}}
-FMS ID: {{update.report.id}}
+Title: {{update.report.title|safe}}
+Category: {{update.report.category.name}}
+Submitted By: {{update.author|safe}}
+Phone: {{update.phone}}
+Email: {{update.email}}
+FMS ID: {{update.report.id}}
-{{update.desc}}
+{{update.desc|safe}}
-Submitted via FixMyStreet.ca on {{update.report.created_at}}.
+Submitted via FixMyStreet.ca on {{update.report.created_at|date}}.
{{update.report.get_absolute_url}}
View
2 templates/emails/send_report_to_city/subject.txt
@@ -1 +1 @@
-FixMyStreet.ca: {{update.report.title}}
+FixMyStreet.ca: {{update.report.title|safe}}
View
2 templates/emails/subscribe/message.txt
@@ -2,7 +2,7 @@ Please click on the following URL:
{{confirm_url}}
To confirm your subscription to updates on the report:
-{{subscriber.report.title}}
+{{subscriber.report.title|safe}}
Thank you,
The FixMyStreet.ca Team
View
2 templates/index.html
@@ -51,7 +51,7 @@
<li>{% trans "Enter a nearby postal code, or street name and city" %}</li>
<li>{% trans "Locate the problem on a map of the area" %}</li>
<li>{% trans "Enter details of the problem" %}</li>
- <li>{% trans "We send it to the City on your behalf" %}</li>
+ <li>{% trans "We send it to the city on your behalf" %}</li>
</ol>
</div>
<div class='block'>
View
2 templates/reports/new.html
@@ -95,7 +95,7 @@
<li>{% trans "Please be polite, concise and to the point." %}</li>
<li>{% trans "Please do not be abusive - abusing the service devalues the service for all users." %}</li>
<li>{% trans "Writing your message entirely in block capitals makes it hard to read, as does a lack of punctuation." %}</li>
- <li>{% trans "Remember that FixMyStreet is primarily for reporting physical problems that can be fixed. If your problem is not appropriate for submission via this site remember that you can contact city officials directly at #311." %}</li>
+ <li>{% trans "Remember that FixMyStreet is primarily for reporting physical problems that can be fixed. If your problem is not appropriate for submission via this site please contact city officials directly." %}</li>
</ul>
<p/>
</div>
View
11 templates/reports/show.html
@@ -52,11 +52,8 @@
{% trans "Filed by:" %}{{report.author}}<br/>
<i>
{% if report.sent_at %}
- {% trans "Sent to " %} {{report.email_sent_to}}<br/>{% trans "on" %} {{report.sent_at|date:"l, F dS, Y"}}.
- {% else %}
- {% if report.is_confirmed %}
- {% blocktrans with report.ward.city.name as city %}This report will be sent to the city of {{city}} in the next 24 hrs.{% endblocktrans %}
- {% endif %}
+ {% trans "Sent to" %}: {{report.email_sent_to}}<br/>
+ {% trans "On" %}: {{report.sent_at|date}}.
{% endif %}
</i>
<br/>
@@ -70,7 +67,7 @@
</div>
{% endif %}
</div>
-
+ <br/>
<p>{{report.desc|linebreaks}}</p>
{% if report.photo %}
<img align=center' src='/media/{{report.photo}}'>
@@ -83,7 +80,7 @@
{% if updates %}
<h3>{% trans "Updates" %}</h3>
{% for update in updates %}
- {% trans "posted by" %} {{update.author}}, {{update.created_at|date:"l, F dS, Y"}}
+ {% trans "posted by" %} {{update.author}}, {{update.created_at|date}}
<br/>
{{update.desc}}
<hr/>
View
8 urls.py
@@ -3,6 +3,8 @@
from django.http import HttpResponseRedirect
from django.contrib import admin
from mainapp.feeds import LatestReports, LatestReportsByCity, LatestReportsByWard, LatestUpdatesByReport
+from mainapp.models import City
+import mainapp.views.cities as cities
feeds = {
'reports': LatestReports,
@@ -41,9 +43,9 @@
)
-urlpatterns += patterns('mainapp.views.cities',
- (r'^cities/(\d+)$', 'show'),
- (r'^cities', 'index'),
+urlpatterns += patterns('',
+ (r'^cities/(\d+)$', cities.show ),
+ (r'^cities', cities.index),
)
urlpatterns += patterns( 'mainapp.views.reports.updates',

0 comments on commit b4727ae

Please sign in to comment.
Something went wrong with that request. Please try again.