# cc2 <http://cc2.berlios.de/> is a web application to drive
# grassroot initiatives.
#
# Copyright (C) 2009 Alberto Granzotto <agranzot@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import turbogears as tg
from turbogears import controllers, expose, flash, config, util
from turbogears import identity, redirect, validate, error_handler, exception_handler
from turbogears.database import session
from cherrypy import request, response, session as cp_session
from cc2.utils import *
from cc2.model import *
from forms import *
from data_grids import *
from cc2.widgets import *
from cc2.other_validators import *
import turbomail
import turbowiki
from sqlalchemy.orm import eagerload
import cStringIO as StringIO
from datetime import date
import os
class CandidateController(controllers.Controller):
@expose()
def index(self, *args, **kw):
raise redirect('/candidate/subscribe')
@expose('cc2.templates.error')
def error(self, tg_errors=None, tg_exceptions=None):
return dict(error_message=tg_errors, exception_messages=tg_exceptions)
@expose('cc2.templates.manage.genericform')
@error_handler(error)
@validate(validators={'id': CheckExistance(query=District.query().get)})
@identity.require(identity.has_permission('create_candidate'))
def create(self, id):
return dict(
title=_('Create a Candidate'), form=candidate_form,
submit_text=_('save'), action='../do_create/%s'%id, values=None)
@expose()
@error_handler(create)
@validate(form=candidate_form,
validators={'id': CheckExistance(query=District.query.get)})
@identity.require(identity.has_permission('create_candidate'))
def do_create(self, id, **kw):
politician = kw['politician']
district = District.query.get(id)
election = district.election
candidate = politician.candidate
if not candidate or not candidate.election == election:
candidate = Candidate()
candidate.politician = politician
candidate.party = politician.party
candidate.election = election
session.save(candidate)
candidate.agrees = kw['agrees']
candidate.elected = kw['elected']
candidate.info = kw['info']
# we need the ID before saving the document
session.flush()
candidate.save_signed_document(kw['signed_document'])
roll = ElectoralRoll()
roll.position = kw['position']
roll.candidate = candidate
roll.district = district
session.save(roll)
session.flush()
session.save(Actionlog(
user_id=identity.current.user_id,
action='C',
description='candidate create',
model_name=Candidate.__name__,
object_id=candidate.id)
)
session.flush()
flash(_('You have created candidate %s') % (politician.full_name))
raise redirect('/election/details/%s' % election.id)
@expose('cc2.templates.candidate.update')
@error_handler(error)
@identity.require(identity.has_permission('update_candidate'))
@validate(validators={'id': CheckExistance(query=ElectoralRoll.query.get)})
def update(self, id):
er = ElectoralRoll.query.get(id)
candidate = er.candidate
foo = Foo(candidate)
foo.position = er.position
foo.back_to = request.headers.get('Referer', '/')
return dict(
title=_('Update Candidate %s') % candidate.politician.full_name,
form=update_candidate_form, submit_text=_('update'),
action='../do_update/%s' % id, values=foo,
signed_documents=candidate.signed_documents)
@expose()
@error_handler(update)
@identity.require(identity.has_permission('update_candidate'))
@validate(form=update_candidate_form,
validators={'id': CheckExistance(query=ElectoralRoll.query.get)})
def do_update(self, id, **kw):
er = ElectoralRoll.query.get(id)
candidate = er.candidate
elected = not candidate.elected and kw['elected']
er.position = kw['position']
candidate.agrees = kw['agrees']
candidate.elected = kw['elected']
candidate.info = kw['info']
politician = candidate.politician
election = candidate.election
candidate.save_signed_document(kw['signed_document'])
session.flush()
session.save(Actionlog(
user_id=identity.current.user_id,
action='U',
description='candidate update',
model_name=Candidate.__name__,
object_id=candidate.id)
)
if elected:
session.save(Actionlog(
user_id=identity.current.user_id,
action='U',
description='candidate elected',
model_name=Candidate.__name__,
object_id=candidate.id)
)
session.flush()
flash(_('You have updated %s') % (politician.full_name))
raise redirect(kw.get('back_to','/'))
@expose('cc2.templates.candidate.select_election')
def subscribe(self):
page = Page.failsafe_by_name('internal.candidate_subscribe')
data = []
query = Election.query().filter(date.today()<=Election.end)
for election in query:
f=Foo()
f.id = election.id
f.type = election.election_type.name
f.pretty_date= election.pretty_date
f.where = election.place.name
data.append(f)
#if len(data) == 0:
# flash(_('there are no active elections'))
# raise redirect('/')
return dict(elections=data, name=page.name, title=_('Select an Election'), page=page)
@expose('cc2.templates.candidate.subscribe')
@error_handler(error)
@validate(validators={'election_id': CheckExistance(query=Election.query.get)})
def sign(self, election_id, tg_errors=None, **kw):
page = Page.failsafe_by_name('internal.candidate_sign')
election = Election.query().get(election_id)
f=Foo(election)
f.type = election.election_type.name
f.interval = '%s-%s' % (election.start.day,
election.end.strftime('%d %B %Y'))
f.where = election.place.name
tg.errors = tg_errors
kw['workgroup_id']=1
if not cp_session.has_key('candidate_subscribe_election_id') or\
cp_session['candidate_subscribe_election_id'] != election_id:
cp_session['candidate_subscribe_election_id'] = election_id
cp_session['candidate_subscribe_form'] =\
candidate_subscribe_form_generator(election_id)
return dict(
title=_('Subscribe the Petition'),
form=cp_session['candidate_subscribe_form'],
page=page, election=f,
submit_text=_('sign'),
action='/candidate/thank_you/%s'%election_id, values=kw)
def get_form(self):
if not cp_session.has_key('candidate_subscribe_election_id'):
flash(_('Session expired, please start again'))
raise redirect('/candidate/subscribe')
return cp_session.get('candidate_subscribe_form', None)
#@expose()
@expose('cc2.templates.candidate.thank_you')
@error_handler(sign)
@validate(form=get_form,
validators={'election_id': CheckExistance(
query=Election.query.get)})
def thank_you(self, election_id, **kw):
del cp_session['candidate_subscribe_form']
del cp_session['candidate_subscribe_election_id']
election = Election.query().get(election_id)
desc = u'''
name = %(name)s
surname = %(surname)s
birthdate = %(pretty_birthdate)s
phone_number = %(phone_number)s
email = %(email)s
site = %(site)s
party = %(party)s
election = %(election)s
association = %(association)s
fax number = %(association_fax)s
email = %(association_email)s
---------------------------
districts positions
'''
if not election.multiple:
for district in election.districts:
key = 'district_%s' % district.id
if kw.has_key(key) and kw[key] and kw[key].strip():
desc += u'%s - %s\n' % (district.name, kw[key])
else:
desc += u'%s - %s\n' % (kw['location'], kw['district'])
kw['election'] = election.name
if kw['birthdate']:
kw['pretty_birthdate'] = kw['birthdate'].strftime('%d/%m/%Y')
else:
kw['pretty_birthdate'] = '???'
wg = Workgroup.query().get(kw['workgroup_id'])
kw['association'] = wg.display_name
kw['association_fax'] = wg.fax
kw['association_email'] = wg.email
key = random_key()
ticket = Ticket(
reporter='%s %s' % (kw['name'],kw['surname']),
reporter_email=kw['email'],
reporter_ip=get_ip_addr(),
type='candidate request',
status='new',
description=desc % kw,
resp_workgroup_id=wg.id,
confidential=True,
model_name='Election',
object_id=election_id,
key=key
)
session.save(ticket)
session.flush()
session.save(Actionlog(
user_id=identity.current.user_id,
action='C',
description='candidate request',
model_name=Ticket.__name__,
object_id=ticket.id)
)
session.flush()
data = dict(
name = kw['name'],
document_url = config.get('siteurl'),
pdf_url = '%scandidate/pdf/%s/subscription.pdf' %\
(config.get('siteurl'), key),
ticket_url = '%sticket/group/new' % config.get('siteurl'),
)
message = turbomail.Message(config.get('mail.sender'), kw['email'],
_('Dear Candidate thanks you for your subscribe'))
message.plain = _(u'''Dear %(name)s,
you have just subscribed our initiative:
* %(document_url)s
To download your PDF again please visit:
* %(pdf_url)s''') % data
turbomail.enqueue(message)
for user in wg.active_users:
message = turbomail.Message(
config.get('mail.sender'),
user.email_address,
_('[cc2] new Candidate subscription'))
message.plain = _(u'''New subscription from %(name)s.
You can see the ticket here:
* %(ticket_url)s''') % data
turbomail.enqueue(message)
page = Page.failsafe_by_name('internal.candidate_thank_you')
flash(_('Your request well be processed as soon as possible'))
pdf_url = '%scandidate/pdf/%s/subscription.pdf' %\
(config.get('siteurl'), key)
formatted_text = turbowiki.wiki_parser(page.text % kw).decode('utf8')
return dict(title=_('Thank you'), pdf_url=pdf_url, page=page,
formatted_text=formatted_text)
@expose(content_type="application/pdf")
@error_handler(error)
@exception_handler(error)
@validate(validators={'key': CheckExistance(query=Ticket.by_key)})
def pdf(self, key, name):
#LOL: name is only for the file name
ticket = Ticket.by_key(key)
election = Election.query.get(ticket.object_id)
document = election.document
template = election.template
#ok, I know, this is awful but I have no time
d = ticket.description.split('\n')
f=Foo()
f.name = d[1][15:]
f.surname = d[2][15:]
f.birthdate = d[3][15:]
f.phone_number = d[4][15:]
f.email = d[5][15:]
f.site = d[6][15:]
f.party = d[7][15:]
f.election = d[8][15:]
f.association = d[9][15:]
f.association_fax = d[10][15:]
f.association_email = d[11][15:]
f.districts = ', '.join(d[15:])
f.document = document.text
text = template.text % f
#FIXME: uhm, wikiparse return a string, we need a unicode object...
text = turbowiki.wiki_parser(text).decode('utf8')
try:
file = pdfize(text)
except:
send_pdf_exception_email()
raise redirect('/error')
if not file:
send_pdf_exception_email()
raise redirect('/error')
return file.getvalue()
@expose(content_type="application/pdf")
@error_handler(error)
@exception_handler(error)
@identity.require(identity.in_group('editor'))
def test_pdf(self, template_name, name):
#LOL: name is only for the file name
template = Page.by_name(template_name)
#ok, I know, this is awful but I have no time
f=Foo()
f.name = 'Name-Test'
f.surname = 'Surname-Test'
f.birthdate = '01/01/1990'
f.phone_number = '+(0)12phone-number345'
f.email = 'email@example.com'
f.site = 'http://www.example.com/'
f.party = 'Party-test'
f.election = 'Election-name-test'
f.association = 'Trusted-association-test'
f.association_fax = '012association-fax34'
f.association_email = 'association-email@example.com'
f.districts = ', '.join(['district-1', 'district-2'])
text = template.text % f
#FIXME: uhm, wikiparse returns a string, we need a unicode object...
text = turbowiki.wiki_parser(text).decode('utf8')
try:
file = pdfize(text)
except:
send_pdf_exception_email()
raise redirect('/error')
if not file:
send_pdf_exception_email()
raise redirect('/error')
return file.getvalue()
@expose('cc2.templates.manage.genericdelete')
@error_handler(error)
@validate(validators={'id': CheckExistance(query=Candidate.query.get)})
@identity.require(is_mine_or_group(Candidate, 'id'))
def delete(self, id, **kw):
o = Candidate.query().get(id)
what = []
what.append( (
_('positions:'),
[e.position for e in o.electoral_rolls])
)
return dict(title=_('Delete Candidancy'),
what=what,
go_back='/politician/details/%s'%o.politician_id,
go_on='/candidate/do_delete/%s'%id)
@expose()
@error_handler(error)
@validate(validators={'id': CheckExistance(query=Candidate.query.get)})
@identity.require(is_mine_or_group(Candidate, 'id'))
def do_delete(self, id, **kw):
o = Candidate.query().get(id)
session.delete(o)
session.save(Actionlog(
user_id=identity.current.user_id,
action='D',
description='candidate delete',
model_name=Candidate.__name__,
object_id=o.id)
)
session.flush()
flash(_('You have deleted %s %s') %
(o.politician.name, o.politician.surname))
raise redirect("/")
@expose('cc2.templates.manage.genericdelete')
@error_handler(error)
@identity.require(identity.has_permission('delete_candidate'))
@validate(validators={'id': CheckExistance(query=ElectoralRoll.query.get)})
def delete_position(self, id, **kw):
o = ElectoralRoll.query().get(id)
what = []
return dict(title=_('Delete Position'),
what=what,
go_back='/politician/details/%s'%o.candidate.politician_id,
go_on='/candidate/do_delete_position/%s'%id)
@expose()
@error_handler(error)
@identity.require(identity.has_permission('delete_candidate'))
@validate(validators={'id': CheckExistance(query=ElectoralRoll.query.get)})
def do_delete_position(self, id, **kw):
o = ElectoralRoll.query().get(id)
session.delete(o)
session.save(Actionlog(
user_id=identity.current.user_id,
action='D',
description='position delete',
model_name=ElectoralRoll.__name__,
object_id=o.id)
)
session.flush()
flash(_('You have deleted %s') % o.position)
raise redirect('/politician/details/%s'%o.candidate.politician_id)