class Timeslot(db.TimeStampedBase): schedule = db.String(choices=[ "once", "weekly", "daily", "exception", "offday", "monthly (date)", "monthly (day)" ]) when = db.DateTime() duration = db.Float() # hours def stewardship(self): return Stewardship.query( Stewardship.timeslots.contains(self.key.urlsafe())).get() def task(self): return Task.query(Task.timeslots.contains(self.key.urlsafe())).get() def slotter(self): return self.task() or self.stewardship() def beforeedit(self, edits): sched = edits.get("sched") if sched == "daily" or sched == "weekly" and self.schedule == "once": return task = self.task() task and task.downschedule() def beforeremove(self, session): slotter = self.slotter() if slotter: # no slotter if slotter is deleting itself.... slotter.timeslots = list( filter(lambda x: x != self.key, slotter.timeslots)) slotter.put(session)
class Expense(Verifiable): executor = db.ForeignKey(kind="Person") # reimbursement only variety = db.String(choices=["dividend", "reimbursement"]) amount = db.Float(default=0.1) # for dividend, split amount * total recurring = db.Boolean(default=False) def dividend(self): pod = self.pod() pool = pod.pool.get() people = db.get_multi(pod.members()) div = self.amount * pool.outstanding cut = div / len(people) for person in people: person.wallet.get().deposit(cut, pod, self, "dividend") pool.debit(div, pod, self, "dividend") # reimbursement requires $$ conversion... def reimbursement(self): pass def fulfill(self): if (self.passed and not self.recurring) or not self.verified(): return False getattr(self, self.variety)() return True
class Payment(Verifiable): payer = db.ForeignKey(kind="Person") amount = db.Float() def signers(self): return [self.payer] def fulfill(self): if self.passed or not self.verified(): return False payer = self.payer.get() memship = self.membership.get() recip = memship.person.get() pod = memship.pod.get() payer.wallet.get().debit(self.amount, pod, self, "payment to %s" % (recip.email, ), self.notes) memship.deposit(self.amount, self, "payment from %s" % (payer.email, ), self.notes, pay=True) self.passed = True self.put() body = PAID % (self.amount, payer.email, recip.email, pod.name, self.notes) for target in [payer, recip]: send_mail(to=target.email, subject="payment confirmation", body=body) return True
class ZipCode(db.ModelBase): code = db.String() city = db.String() state = db.String() county = db.String() latitude = db.Float() longitude = db.Float() label = "code" def __str__(self): return self.code def latlng(self): self.latitude, self.longitude = address2latlng(self.code) self.put() def fullString(self): return "%s, %s, %s" % (self.city, self.state, self.code)
class Commitment(Verifiable): service = db.ForeignKey(kind="Service") estimate = db.Float(default=1.0) # per week (hours?) def deposit(self, numdays=1): service = self.service.get() details = "compensating commitment: %s service (%s); estimated %s hours per week; paying for %s days" % ( service.name, service.compensation, self.estimate, numdays) log(details) self.membership.get().deposit( service.compensation * self.estimate * numdays / 7.0, self, "commitment: %s" % (service.name, ), details)
class Adjustment(Proposal): variety = db.String() # already has name! compensation = db.Float(default=1.0) def oncreate(self): convo = Conversation(topic=self.name) convo.put() self.conversation = convo.key service = self.service() self.notify( "compensation adjustment proposed", lambda signer: ADJUSTMENT % (self.name, self.variety, service.compensation, self.compensation, self.description)) def onpass(self): serv = self.service() self.notify( "compensation adjustment approved", lambda signer: ADJUSTED % (self.name, self.variety, serv.compensation, self.compensation, self.description)) serv.compensation = self.compensation serv.put() def notify(self, subject, body): for signer in self.voters(): send_mail(to=signer.get().email, subject=subject, body=body(signer)) def service(self): return Service.query(Service.name == self.name, Service.variety == self.variety).get() def voters(self): peeps = set() for pod in Pod.query(Pod.variety == self.variety).all(): peeps.update([k.urlsafe() for k in pod.members()]) return [db.KeyWrapper(p) for p in list(peeps)] def votership(self): return len(self.voters())
class Service(db.TimeStampedBase): name = db.String() variety = db.String() compensation = db.Float(default=1.0)
class Place(db.TimeStampedBase): latitude = db.Float() longitude = db.Float() address = db.String() zipcode = db.ForeignKey(kind="zipcode") label = "address"