]> asedeno.scripts.mit.edu Git - bluechips.git/blobdiff - bluechips/controllers/spend.py
Fix division of currency
[bluechips.git] / bluechips / controllers / spend.py
index c99d325ba10984b2fd1da0a508cf9479668ca8b3..8000fd377a8a331b6efc0e73e85f726b1726eda5 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,15 +30,22 @@ 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
     pre_validators = [NestedVariables()]
     spender_id = validators.Int(not_empty=True)
     amount = model.types.CurrencyValidator(not_empty=True)
 class ExpenditureSchema(Schema):
     "Validate an expenditure."
     allow_extra_fields = False
     pre_validators = [NestedVariables()]
     spender_id = validators.Int(not_empty=True)
     amount = model.types.CurrencyValidator(not_empty=True)
-    description = validators.UnicodeString()
+    description = validators.UnicodeString(not_empty=True)
     date = validators.DateConverter()
     shares = ForEach(ShareSchema)
     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('/')