2011-07-23 18:45:40 +02:00
from flaskext . wtf import *
2011-10-15 01:58:30 +02:00
from flaskext . babel import lazy_gettext as _
2011-10-08 13:45:05 +02:00
from flask import request
2011-08-10 00:20:16 +02:00
from wtforms . widgets import html_params
2011-09-13 22:58:53 +02:00
from models import Project , Person , Bill , db
2011-08-09 18:28:48 +02:00
from datetime import datetime
2011-09-11 05:25:42 +02:00
from jinja2 import Markup
from utils import slugify
2011-07-23 18:45:40 +02:00
2011-08-10 00:20:16 +02:00
def select_multi_checkbox ( field , ul_class = ' ' , * * kwargs ) :
kwargs . setdefault ( ' type ' , ' checkbox ' )
field_id = kwargs . pop ( ' id ' , field . id )
2011-08-21 01:42:10 +02:00
html = [ u ' <ul %s > ' % html_params ( id = field_id , class_ = " inputs-list " ) ]
2011-10-20 04:18:12 +02:00
choice_id = u ' toggleField '
js_function = u ' toggle(); '
options = dict ( kwargs , id = choice_id , onclick = js_function )
label = _ ( " Select All/None " )
html . append ( u ' <li><label for= " %s " > %s <span> %s </span></label></li> ' % ( choice_id , ' <input %s /> ' % html_params ( * * options ) , label ) )
2011-08-10 00:20:16 +02:00
for value , label , checked in field . iter_choices ( ) :
choice_id = u ' %s - %s ' % ( field_id , value )
options = dict ( kwargs , name = field . name , value = value , id = choice_id )
if checked :
options [ ' checked ' ] = ' checked '
2011-08-21 01:42:10 +02:00
html . append ( u ' <li><label for= " %s " > %s <span> %s </span></label></li> ' % ( choice_id , ' <input %s /> ' % html_params ( * * options ) , label ) )
2011-08-10 00:20:16 +02:00
html . append ( u ' </ul> ' )
return u ' ' . join ( html )
2011-10-08 13:45:05 +02:00
def get_billform_for ( project , set_default = True , * * kwargs ) :
2011-09-11 05:25:42 +02:00
""" Return an instance of BillForm configured for a particular project.
: set_default : if set to True , on GET methods ( usually when we want to
display the default form , it will call set_default on it .
"""
2011-10-08 13:45:05 +02:00
form = BillForm ( * * kwargs )
2011-10-14 15:48:18 +02:00
form . payed_for . choices = form . payer . choices = [ ( m . id , m . name ) for m in project . active_members ]
form . payed_for . default = [ m . id for m in project . active_members ]
2011-09-11 05:25:42 +02:00
if set_default and request . method == " GET " :
form . set_default ( )
return form
2011-11-02 14:35:38 +01:00
class CommaDecimalField ( DecimalField ) :
""" A class to deal with comma in Decimal Field """
def process_formdata ( self , value ) :
2011-11-03 13:33:11 +01:00
if value :
value [ 0 ] = str ( value [ 0 ] ) . replace ( ' , ' , ' . ' )
2011-11-02 14:35:38 +01:00
return super ( CommaDecimalField , self ) . process_formdata ( value )
2011-09-11 05:25:42 +02:00
2011-10-08 13:45:05 +02:00
2011-09-14 22:03:18 +02:00
class EditProjectForm ( Form ) :
2011-10-15 01:19:19 +02:00
name = TextField ( _ ( " Project name " ) , validators = [ Required ( ) ] )
password = TextField ( _ ( " Private code " ) , validators = [ Required ( ) ] )
contact_email = TextField ( _ ( " Email " ) , validators = [ Required ( ) , Email ( ) ] )
2011-08-10 17:06:32 +02:00
2011-07-23 19:11:24 +02:00
def save ( self ) :
""" Create a new project with the information given by this form.
Returns the created instance
"""
project = Project ( name = self . name . data , id = self . id . data ,
password = self . password . data ,
contact_email = self . contact_email . data )
return project
2011-09-13 22:58:53 +02:00
def update ( self , project ) :
""" Update the project with the information from the form """
project . name = self . name . data
project . password = self . password . data
project . contact_email = self . contact_email . data
return project
2011-09-18 23:38:12 +02:00
2011-09-14 22:03:18 +02:00
class ProjectForm ( EditProjectForm ) :
2011-10-15 01:19:19 +02:00
id = TextField ( _ ( " Project identifier " ) , validators = [ Required ( ) ] )
password = PasswordField ( _ ( " Private code " ) , validators = [ Required ( ) ] )
submit = SubmitField ( _ ( " Create the project " ) )
2011-07-23 18:45:40 +02:00
2011-08-10 17:06:32 +02:00
def validate_id ( form , field ) :
2011-09-11 05:25:42 +02:00
form . id . data = slugify ( field . data )
if Project . query . get ( form . id . data ) :
2011-10-15 01:19:19 +02:00
raise ValidationError ( Markup ( _ ( " The project identifier is used to log in and for the URL of the project. We tried to generate an identifier for you but a project with this identifier already exists. Please create a new identifier you will be able to remember. " ) ) )
2011-08-10 17:06:32 +02:00
2011-07-23 18:45:40 +02:00
class AuthenticationForm ( Form ) :
2011-10-15 01:19:19 +02:00
id = TextField ( _ ( " Project identifier " ) , validators = [ Required ( ) ] )
password = PasswordField ( _ ( " Private code " ) , validators = [ Required ( ) ] )
submit = SubmitField ( _ ( " Get in " ) )
2011-07-23 18:45:40 +02:00
2011-10-08 15:52:12 +02:00
class PasswordReminder ( Form ) :
2011-10-15 01:19:19 +02:00
id = TextField ( _ ( " Project identifier " ) , validators = [ Required ( ) ] )
submit = SubmitField ( _ ( " Send me the code by email " ) )
2011-10-08 15:52:12 +02:00
def validate_id ( form , field ) :
if not Project . query . get ( field . data ) :
2011-10-15 01:19:19 +02:00
raise ValidationError ( _ ( " This project does not exists " ) )
2011-10-08 15:52:12 +02:00
2011-07-23 18:45:40 +02:00
class BillForm ( Form ) :
2011-10-15 01:19:19 +02:00
date = DateField ( _ ( " Date " ) , validators = [ Required ( ) ] , default = datetime . now )
what = TextField ( _ ( " What? " ) , validators = [ Required ( ) ] )
payer = SelectField ( _ ( " Payer " ) , validators = [ Required ( ) ] , coerce = int )
2011-11-02 14:35:38 +01:00
amount = CommaDecimalField ( _ ( " Amount paid " ) , validators = [ Required ( ) ] )
2011-10-20 04:18:12 +02:00
payed_for = SelectMultipleField ( _ ( " For whom? " ) ,
2011-10-14 15:48:18 +02:00
validators = [ Required ( ) ] , widget = select_multi_checkbox , coerce = int )
2011-10-15 01:19:19 +02:00
submit = SubmitField ( _ ( " Send the bill " ) )
2011-07-23 18:45:40 +02:00
2011-10-08 13:22:18 +02:00
def save ( self , bill , project ) :
2011-08-10 12:59:30 +02:00
bill . payer_id = self . payer . data
bill . amount = self . amount . data
bill . what = self . what . data
bill . date = self . date . data
2011-11-28 01:07:06 +01:00
bill . owers = [ Person . query . get ( ower , project ) for ower in self . payed_for . data ]
2011-07-31 00:41:28 +02:00
return bill
2011-08-10 12:59:30 +02:00
def fill ( self , bill ) :
self . payer . data = bill . payer_id
self . amount . data = bill . amount
self . what . data = bill . what
self . date . data = bill . date
2011-11-28 01:07:06 +01:00
self . payed_for . data = [ int ( ower . id ) for ower in bill . owers ]
2011-08-10 12:59:30 +02:00
def set_default ( self ) :
self . payed_for . data = self . payed_for . default
2011-10-18 18:13:54 +02:00
def validate_amount ( self , field ) :
if field . data < 0 :
2011-11-02 14:35:38 +01:00
field . data = abs ( field . data )
elif field . data == 0 :
raise ValidationError ( _ ( " Bills can ' t be null " ) )
2011-10-18 18:13:54 +02:00
2011-07-23 20:36:13 +02:00
class MemberForm ( Form ) :
2011-11-20 14:37:32 +01:00
name = TextField ( _ ( " Name " ) , validators = [ Required ( ) ] , default = _ ( " Type user name here " ) )
2011-11-01 12:57:12 +01:00
submit = SubmitField ( _ ( " Add " ) )
2011-07-23 20:36:13 +02:00
2011-09-13 22:58:53 +02:00
def __init__ ( self , project , * args , * * kwargs ) :
super ( MemberForm , self ) . __init__ ( * args , * * kwargs )
self . project = project
2011-07-23 20:36:13 +02:00
def validate_name ( form , field ) :
2011-11-20 14:37:32 +01:00
if field . data == form . name . default :
raise ValidationError ( _ ( " User name incorrect " ) )
2011-07-30 01:51:13 +02:00
if Person . query . filter ( Person . name == field . data ) \
2011-08-22 23:19:00 +02:00
. filter ( Person . project == form . project ) \
. filter ( Person . activated == True ) . all ( ) :
2011-10-15 01:19:19 +02:00
raise ValidationError ( _ ( " This project already have this member " ) )
2011-07-30 15:46:53 +02:00
2011-09-13 22:58:53 +02:00
def save ( self , project , person ) :
# if the user is already bound to the project, just reactivate him
person . name = self . name . data
person . project = project
return person
2011-07-31 00:41:28 +02:00
2011-07-30 15:46:53 +02:00
class InviteForm ( Form ) :
2011-10-15 01:19:19 +02:00
emails = TextAreaField ( _ ( " People to notify " ) )
submit = SubmitField ( _ ( " Send invites " ) )
2011-07-30 15:46:53 +02:00
def validate_emails ( form , field ) :
validator = Email ( )
for email in [ email . strip ( ) for email in form . emails . data . split ( " , " ) ] :
if not validator . regex . match ( email ) :
2011-10-15 01:19:19 +02:00
raise ValidationError ( _ ( " The email %(email)s is not valid " ,
email = email ) )
2011-08-10 00:20:16 +02:00
2011-09-09 19:14:19 +02:00
class CreateArchiveForm ( Form ) :
2011-10-15 01:19:19 +02:00
start_date = DateField ( _ ( " Start date " ) , validators = [ Required ( ) , ] )
end_date = DateField ( _ ( " End date " ) , validators = [ Required ( ) , ] )
name = TextField ( _ ( " Name for this archive (optional) " ) )