class Answer(db.TimeStampedBase): prompt = db.String() response = db.Text() rating = db.Integer() # 1-5 def full(self): return "\n".join([self.prompt, self.response, str(self.rating)])
class Resource(Place): editors = db.ForeignKey(kind="Person", repeated=True) name = db.String() description = db.Text() tags = db.ForeignKey(kind=Tag, repeated=True) icon = db.String() # refers to ctmap graphic resource label = "name" def _pre_trans_zipcode(self, val): if isinstance(val, string_types) and len(val) < 10: val = getzip(val).key return val def total(self): return config.ctcomp.ratios.resource def oncreate(self): zcode = self.zipcode.get() addr = "%s, %s, %s" % (self.address, zcode.city, zcode.state) self.latitude, self.longitude = address2latlng(addr) def notify(self, podname, interested): bod = RESOURCE % (podname, self.name, self.description) for person in interested: send_mail(to=person.email, subject="new message board", body=bod)
class Verifiable(db.TimeStampedBase): membership = db.ForeignKey(kind="Membership") passed = db.Boolean(default=False) notes = db.Text() def pod(self, noget=False): pod = self.membership.get().pod return noget and pod or pod.get() def signers(self): return self.pod().members() def fulfill(self): if not self.verified(): return False self.passed = True self.put() return True def notify(self, subject, body, signers=None): for signer in (signers or self.signers()): if self.unverified(signer): send_mail(to=signer.get().email, subject=subject, body=body(signer)) def unverify(self): log("unverifying %s" % (self.key.urlsafe(), )) sigs = Verification.query(Verification.act == self.key).fetch() log("unsigning %s verifications" % (len(sigs), ), 1) db.delete_multi(sigs) log("unpassing", 1) self.passed = False self.put() def verify(self, person): if person in self.signers(): if Verification.query(Verification.act == self.key, Verification.person == person).get(): return log("already verified (%s %s)!" % (self.key, person), important=True) log("verification (%s %s) success" % (self.key.urlsafe(), person.urlsafe())) Verification(act=self.key, person=person).put() return self.fulfill() log("verification attempt (%s %s) failed -- unauthorized" % (self.key, person)) def veriquery(self): return Verification.query(Verification.act == self.key) def unverified(self, person): return not self.veriquery().filter(Verification.person == person).get() def verified(self): for person in self.signers(): if self.unverified(person): return False return True
class Contactable(db.TimeStampedBase): tags = db.ForeignKey(kind=Tag, repeated=True) member = db.ForeignKey() name = db.String() email = db.String() phone = db.String() address = db.String() description = db.Text() # only required field closed = db.Boolean(default=False) ongoing = db.Boolean(default=False)
class LibItem(db.TimeStampedBase): content = db.ForeignKey(kind="Content") editors = db.ForeignKey(kind="Person", repeated=True) name = db.String() description = db.Text() tags = db.ForeignKey(kind=Tag, repeated=True) label = "name" def notify(self, podname, interested): bod = LIBITEM % (podname, self.name, self.description) for person in interested: send_mail(to=person.email, subject="new message board", body=bod)
class Feedback(db.TimeStampedBase): person = db.ForeignKey(kind=Person) conversation = db.ForeignKey(kind=Conversation) interaction = db.ForeignKey(kinds=[Appointment, Delivery, Request]) answers = db.ForeignKey(kind=Answer, repeated=True) topic = db.String() notes = db.Text() followup = db.Boolean(default=False) def membership(self): from .util import membership return membership(self.person.get(), self.pod()) def pod(self): return self.interaction.get().pod() def full(self): answers = "\n\n".join([a.full() for a in db.get_multi(self.answers)]) return "\n\n".join([ self.topic, answers, self.notes, "request follow up: %s" % (self.followup, ) ]) def notify(self): bod = FEEDBACK % (self.person.get().firstName, self.pod().name, self.full(), self.key.urlsafe()) self.interaction.get().notify("feedback", lambda signer: bod, self.participants()) def participants(self): pars = self.interaction.get().signers() if self.person not in pars: return pars + [self.person] return pars def oncreate(self): convo = Conversation(topic=self.topic) convo.participants = self.participants() convo.put() self.conversation = convo.key self.put() # for notify() key self.notify() if self.followup: req = Request() req.membership = self.membership().key req.change = "conversation" req.notes = self.notes req.put() req.remind()
class Chemical(db.TimeStampedBase): classification = db.String() code = db.String() name = db.String() cas = db.String() rtecs = db.String() dot = db.String() idlh = db.String() synonyms_and_trade_names = db.String() formula = db.String() conversion = db.String() physical_description = db.String() molecular_weight = db.String() boiling_point = db.String() melting_point = db.String() freezing_point = db.String() solubility = db.String() vapor_pressure = db.String() ionization_potential = db.String() specific_gravity = db.String() flash_point = db.String() upper_explosive_limit = db.String() lower_explosive_limit = db.String() incompatibilities_and_reactivities = db.String() exposure_routes = db.String() symptoms = db.String() target_organs = db.String() cancer_site = db.String() respirator_recommendations = db.Text() exposure_limits = db.Text() measurement_methods = db.Text() first_aid = db.Text() personal_protection_sanitation = db.Text() def basic(self): return {"key": self.id(), "name": self.name}
class SecBase(db.TimeStampedBase): name = db.String() description = db.Text() sections = db.ForeignKey(kind="section", repeated=True) def secs(self, sections=None, depth=0, novars=False, page_breaks=False): return "\r\n\r\n".join(sections and [ db.get(s['key']).content(s['sections'], depth, novars, page_breaks) for s in sections ] or [ s.content(depth=depth, novars=novars, page_breaks=page_breaks) for s in db.get_multi(self.sections) ]) def fixed_desc(self, depth=0, novars=False): d = self.description return h2l(novars and d.replace("{{", "(").replace("}}", ")") or d, depth) def desc(self, depth=0, novars=False): return self.fixed_desc(depth, novars) def header(self): return self.name def body(self, depth, novars=False, page_breaks=False): tline = "%s %s" % ("#" * depth, self.header()) if page_breaks and depth == 1: tline = "\\newpage%s" % (tline, ) return "%s\r\n\r\n%s" % (tline, self.desc(depth, novars)) def content(self, sections=None, depth=0, novars=False, page_breaks=False): body = self.body(depth, novars, page_breaks) secs = self.sections and self.secs(sections, depth + 1, novars, page_breaks) or "" cont = "%s\r\n\r\n%s" % (body, secs) log(cont) return cont def unrolled(self): d = self.data() d['sections'] = [s.unrolled() for s in db.get_multi(self.sections)] return d
class Update(db.TimeStampedBase): sender = db.ForeignKey() subject = db.String() message = db.Text() recipients = db.ForeignKey(repeated=True) conversation = db.ForeignKey(kind=Conversation) label = "subject" def oncreate(self): convo = Conversation(topic=self.subject) convo.put() self.conversation = convo.key if self.recipients: recipients = db.get_multi(self.recipients) else: recipients = Member.query().all() bod = UPDATE % (self.sender.get().email, self.message) for recip in recipients: send_mail(to=recip.email, subject=self.subject, body=bod)
class Invitation(db.TimeStampedBase): membership = db.ForeignKey(kind=Membership) email = db.String() notes = db.Text() def invite(self): memship = self.membership.get() send_mail(to=self.email, subject="invitation", body=INVITATION % (memship.person.get().email, memship.pod.get().name)) def send(self, person): req = Request() req.membership = self.membership req.person = person.key req.change = "include" req.notes = self.notes req.put() req.remind()
class Board(db.TimeStampedBase): name = db.String() description = db.Text() anonymous = db.Boolean(default=False) tags = db.ForeignKey(kind=Tag, repeated=True) conversation = db.ForeignKey(kind=Conversation) label = "name" def pod(self): from .core import Pod return Pod.query(Pod.boards.contains(self.key.urlsafe())).get() def notify(self, podname, interested): bod = BOARD % (podname, self.name, self.description) for person in interested: send_mail(to=person.email, subject="new message board", body=bod) def oncreate(self): convo = Conversation(topic=self.name) convo.anonymous = self.anonymous convo.put() self.conversation = convo.key
class Task(db.TimeStampedBase): editors = db.ForeignKey(repeated=True) timeslots = db.ForeignKey(kind=Timeslot, repeated=True) commitments = db.ForeignKey(kind=Stewardship, repeated=True) name = db.String() description = db.Text() mode = db.String() # arbitrary requirements = db.String(repeated=True) steps = db.String(repeated=True) def happening(self, now): slots = [] for slot in db.get_multi(self.timeslots): if isDay(slot, now): slots.append(slot) if len(slots) is 1: # if 2, one is exception return slots[0] def unsteward(self, stewardship, verb="rescheduled"): # just a notifier send_mail(to=stewardship.steward.get().email, subject="commitment update", body=RESCHED % (self.name, verb)) def downschedule(self): stewz = db.get_multi(self.commitments) for stew in stewz: self.unsteward(stew, "rescheduled") self.commitments = [] self.put() db.delete_multi(stewz) def beforeremove(self, session): for stew in db.get_multi(self.commitments, session): self.unsteward(stew, "removed") def afterremove(self, session): db.delete_multi( db.get_multi(self.timeslots + self.commitments, session), session)
class Payment(db.TimeStampedBase): member = db.ForeignKey(kind=Member) successful = db.Boolean(default=False) amount = db.String() duration = db.Integer() # days message = db.Text()
class Pod(db.TimeStampedBase): name = db.String() variety = db.String() blurb = db.Text() pool = db.ForeignKey(kind=Wallet) agent = db.ForeignKey(kind="Pod") needs = db.ForeignKey(kind=Need, repeated=True) tasks = db.ForeignKey(kind=Task, repeated=True) boards = db.ForeignKey(kind=Board, repeated=True) updates = db.ForeignKey(kind=Update, repeated=True) drivers = db.ForeignKey(kind=Person, repeated=True) includers = db.ForeignKey(kind=Person, repeated=True) resources = db.ForeignKey(kind=Resource, repeated=True) offerings = db.ForeignKey(kind=Offering, repeated=True) dependencies = db.ForeignKey(kind=Codebase, repeated=True) # software library = db.ForeignKey(kinds=[Organization, Book, Web, Media], repeated=True) # support def _trans_boards(self, val): v = val[-1].get() v.notify(self.name, self.interested(v.tags)) return val def _trans_library(self, val): v = val[-1].get() v.notify(self.name, self.interested(v.tags)) return val def _trans_resources(self, val): v = val[-1].get() v.notify(self.name, self.interested(v.tags)) return val def _trans_needs(self, val): self.notify(val[-1].get(), NEED) return val def _trans_offerings(self, val): self.notify(val[-1].get(), OFFERING) return val def notify(self, item, etemp): bod = etemp % (self.name, item.description) for person in self.interested(item.tags): send_mail(to=person.email, subject="new %s" % (item.polytype, ), body=bod) def interested(self, tags): tagz = set(map(lambda t: t.urlsafe(), tags)) return filter( lambda p: tagz.intersection( set(map(lambda t: t.urlsafe(), p.interests))), db.get_multi(self.members())) def oncreate(self): email_admins("New Pod", "name: %s\nvariety: %s" % (self.name, self.variety)) if not self.pool: w = Wallet() w.put() self.pool = w.key def codebases(self): return Codebase.query(Codebase.pod == self.key).fetch() def _collection(self, mod): return sum([ mod.query(mod.membership == m.key).fetch() for m in self.members(True) ], []) def expenses(self): return self._collection(Expense) def acts(self): return self._collection(Act) def requests(self): return self._collection(Request) def commitments(self): return self._collection(Commitment) def proposals(self): return sum([m.proposals for m in self.members(True)], []) def members(self, noperson=False): mems = Membership.query(Membership.pod == self.key).fetch() return noperson and mems or [mem.person for mem in mems] def deposit(self, member, amount, deed, note, details=None, nocode=False, pay=False): memwall = member.wallet.get() if pay: memcut = amount * ratios.pay amount -= memcut memwall.deposit(memcut, self, deed, note, details) else: memwall.deposit(amount, self, deed, note, details) self.pool.get().deposit(amount, self, deed, note, details) self.agent and self.agent.get().pool.get().deposit( amount * ratios.agent, self, deed, note, details) if not nocode: for codebase in self.codebases(): codebase.deposit(amount, deed) depcut = amount * ratios.code.dependency for dependency in db.get_multi(self.dependencies): dependency.deposit(depcut, deed) def service(self, member, service, recipient_count, details): self.deposit(member, service.compensation * recipient_count, service, "service: %s (%s)" % (service.name, service.variety), details) def support_service(self): sname = (self.variety == "support") and self.name or "support" service = Service.query(Service.name == sname, Service.variety == self.variety).get() if not service: service = Service(name=sname, variety=self.variety) service.put() return service.key
class PageEdit(db.TimeStampedBase): path = db.String() content = db.Text() node_id = db.String()
class Comment(db.TimeStampedBase): user = db.ForeignKey() # CTUser, Author, or whatever else post = db.ForeignKey(kinds=["post", "videopost", "photoset"]) body = db.Text()
class Post(BasePost): img = db.Binary() body = db.Text()
class Survey(db.TimeStampedBase): user = db.ForeignKey(kind=CTUser) demographics = db.ForeignKey(kind=Demographic, repeated=True) title = db.String() blurb = db.Text() instructions = db.Text()
class Answer(db.TimeStampedBase): person = db.ForeignKey(kind=Person) page = db.ForeignKey(kind=Page) question = db.Integer() response = db.Text()
class Demographic(db.TimeStampedBase): prompt = db.Text() options = db.String(repeated=True)
class Style(db.TimeStampedBase): font = db.String() color = db.String() background = db.String() rules = db.Text()