]> asedeno.scripts.mit.edu Git - bluechips.git/blobdiff - bluechips/controllers/spend.py
Convert the README to rST, since that's what distutils wants.
[bluechips.git] / bluechips / controllers / spend.py
index c99d325ba10984b2fd1da0a508cf9479668ca8b3..4e89b35b55c27ed6c0d79cff74609e991aa3d2ae 100644 (file)
@@ -9,13 +9,14 @@ from decimal import Decimal, InvalidOperation
 from bluechips.lib.base import *
 
 from pylons import request, app_globals as g
 from bluechips.lib.base import *
 
 from pylons import request, app_globals as g
-from pylons.decorators.rest import dispatch_on
 from pylons.decorators import validate
 from pylons.decorators import validate
+from pylons.decorators.secure import authenticate_form
 from pylons.controllers.util import abort
 
 from formencode import validators, Schema
 from formencode.foreach import ForEach
 from formencode.variabledecode import NestedVariables
 from pylons.controllers.util import abort
 
 from formencode import validators, Schema
 from formencode.foreach import ForEach
 from formencode.variabledecode import NestedVariables
+from formencode.schema import SimpleFormValidator
 
 from mailer import Message
 
 
 from mailer import Message
 
@@ -29,6 +30,12 @@ class ShareSchema(Schema):
     amount = validators.Number(not_empty=True)
 
 
     amount = validators.Number(not_empty=True)
 
 
+def validate_state(value_dict, state, validator):
+    if all(s['amount'] == 0 for s in value_dict['shares']):
+        return {'shares-0.amount': 'Need at least one non-zero share'}
+ValidateNotAllZero = SimpleFormValidator(validate_state)
+
+
 class ExpenditureSchema(Schema):
     "Validate an expenditure."
     allow_extra_fields = False
 class ExpenditureSchema(Schema):
     "Validate an expenditure."
     allow_extra_fields = False
@@ -38,6 +45,7 @@ class ExpenditureSchema(Schema):
     description = validators.UnicodeString()
     date = validators.DateConverter()
     shares = ForEach(ShareSchema)
     description = validators.UnicodeString()
     date = validators.DateConverter()
     shares = ForEach(ShareSchema)
+    chained_validators = [ValidateNotAllZero]
     
 
 class SpendController(BaseController):
     
 
 class SpendController(BaseController):
@@ -57,10 +65,9 @@ class SpendController(BaseController):
             c.values = {}
             for ii, user_row in enumerate(c.users):
                 user_id, user = user_row
             c.values = {}
             for ii, user_row in enumerate(c.users):
                 user_id, user = user_row
+                val = 0
                 if user.resident:
                     val = Decimal(100) / Decimal(num_residents)
                 if user.resident:
                     val = Decimal(100) / Decimal(num_residents)
-                else:
-                    val = 0
                 c.values['shares-%d.amount' % ii] = val
         else:
             c.title = 'Edit an Expenditure'
                 c.values['shares-%d.amount' % ii] = val
         else:
             c.title = 'Edit an Expenditure'
@@ -70,18 +77,21 @@ class SpendController(BaseController):
             c.values = {}
             for ii, user_row in enumerate(c.users):
                 user_id, user = user_row
             c.values = {}
             for ii, user_row in enumerate(c.users):
                 user_id, user = user_row
-                try:
-                    share = [s.share for s in c.expenditure.splits
-                             if s.user == user][0]
+                shares_by_user = dict(((sp.user, sp.share) for sp
+                                       in c.expenditure.splits))
+                share = shares_by_user.get(user, 0)
+                if c.expenditure.amount == 0:
+                    percent = 0
+                else:
                     percent = (Decimal(100) * Decimal(int(share)) /
                                Decimal(int(c.expenditure.amount))).\
                             quantize(Decimal("0.001"))
                     percent = (Decimal(100) * Decimal(int(share)) /
                                Decimal(int(c.expenditure.amount))).\
                             quantize(Decimal("0.001"))
-                except IndexError:
-                    percent = 0
                 c.values['shares-%d.amount' % ii] = percent
 
         return render('/spend/index.mako')
 
                 c.values['shares-%d.amount' % ii] = percent
 
         return render('/spend/index.mako')
 
+    @redirect_on_get('edit')
+    @authenticate_form
     @validate(schema=ExpenditureSchema(), form='edit', variable_decode=True)
     def update(self, id=None):
         # Either create a new object, or, if we're editing, get the
     @validate(schema=ExpenditureSchema(), form='edit', variable_decode=True)
     def update(self, id=None):
         # Either create a new object, or, if we're editing, get the
@@ -99,8 +109,6 @@ class SpendController(BaseController):
         # Set the fields that were submitted
         shares = self.form_result.pop('shares')
         update_sar(e, self.form_result)
         # Set the fields that were submitted
         shares = self.form_result.pop('shares')
         update_sar(e, self.form_result)
-        if e.id is not None:
-            e.update_split()
 
         users = dict(meta.Session.query(model.User.id, model.User).all())
         split_dict = {}
 
         users = dict(meta.Session.query(model.User.id, model.User).all())
         split_dict = {}
@@ -124,3 +132,35 @@ class SpendController(BaseController):
         g.handle_notification(involved_users, show, body)
 
         return h.redirect_to('/')
         g.handle_notification(involved_users, show, body)
 
         return h.redirect_to('/')
+
+    def delete(self, id):
+        c.title = 'Delete an Expenditure'
+        c.expenditure = meta.Session.query(model.Expenditure).get(id)
+        if c.expenditure is None:
+            abort(404)
+
+        return render('/spend/delete.mako')
+
+    @redirect_on_get('delete')
+    @authenticate_form
+    def destroy(self, id):
+        e = meta.Session.query(model.Expenditure).get(id)
+        if e is None:
+            abort(404)
+
+        if 'delete' in request.params:
+            meta.Session.delete(e)
+
+            meta.Session.commit()
+            show = ("Expenditure of %s paid for by %s deleted." %
+                    (e.amount, e.spender))
+            h.flash(show)
+
+            involved_users = set(sp.user for sp in e.splits if sp.share != 0)
+            involved_users.add(e.spender)
+            body = render('/emails/expenditure.txt',
+                          extra_vars={'expenditure': e,
+                                      'op': 'deleted'})
+            g.handle_notification(involved_users, show, body)
+
+        return h.redirect_to('/')