class Program(Entity): using_options(tablename='programs') caption = Field(Text, default='Program') pi = Field(Text, default='Anonymous Investigator') priority = Field(Integer, default=1000) timeBetweenObservationsMin = Field(Integer, default=0) #Seconds! timeBetweenObservationsMax = Field(Integer, default=0) #Seconds! lastObservationAt = Field(DateTime) constraints = OneToMany('Constraint', inverse='program') observations = OneToMany('Observation', inverse='program')
class Lei(Entity): using_options(tablename='lei_decisao') esfera = Field(Unicode(10)) lei = Field(Unicode(32)) ano = Field(Integer) decisao = ManyToOne('Decisao') artigos = OneToMany('Artigo')
class Exposure(Entity): using_options(tablename='exposures') filter = Field(Text, default='CLEAR') #ASCII value of filter to use frames = Field(Integer, default=1) #Frames to take duration = Field(Integer, default=5) #Seconds per frame binX = Field(Integer, default=1) #X CCD Binning binY = Field(Integer, default=1) #Y CCD Binning windowXCtr = Field(Float, default=0.5) windowYCtr = Field(Float, default=0.5) windowWidth = Field(Float, default=1.0) windowHeight = Field(Float, default=1.0) shutterOpen = Field(Boolean, default=True) imageType = Field(Text, default='object') priority = Field(Integer, default=1000) finished = Field(Boolean, default=False) #Observation finished filename = Field(Text, default='$DATE-$TIME') constraints = OneToMany('Constraint', inverse='exposure') observation = ManyToOne('Observation', inverse='exposures')
class InvCard(Entity): name = Field(UnicodeText, index=True) set_name = Field(UnicodeText) box = Field(UnicodeText) scan_png = Field(BLOB) box_index = Field(Integer) recognition_status = Field( Enum('scanned', 'candidate_match', 'incorrect_match', 'verified')) inventory_status = Field(Enum('present', 'temporarily_out', 'permanently_gone'), index=True) is_foil = Field(Boolean, default=False) language = Field(UnicodeText, default=u'english') condition = Field(Enum('mint', 'near_mint', 'good', 'heavy_play')) inv_logs = OneToMany('InvLog') fix_log = OneToOne('FixLog') rowid = Field(Integer, primary_key=True) using_options(tablename='inv_cards') def most_recent_log(self): return sorted(self.inv_logs, key=lambda x: x.date)[-1] def __unicode__(self): return "<%s/%s (%s/%s)>" % (self.set_name, self.name, self.box, self.box_index) def __str__(self): return unicode(self).encode(sys.stdout.encoding)
class Audience(Entity): """Mapper for the `audience' entity """ using_options(shortnames=True) #msgid = Field(id) id = Field(Integer, primary_key=True) title = Field(Unicode(256)) subject = Field(UnicodeText) description = Field(UnicodeText) date = Field(DateTime) creation_date = Field(DateTime, default=datetime.now) terms = OneToMany('Term') visible = Field(Boolean, default=False) started = Field(Boolean, default=False) date_started = Field(DateTime) owner = Field(Unicode(64)) embed = Field(Unicode(256)) #buzzes = OneToMany('Buzz') def __str__(self): return '<%s "%s" (%d)>' % ( self.__class__.__name__, self.description, self.date) def get_main_term(self): """Returns the main term of the current audience""" return Term.query.filter_by(main=1, audience=self).one().hashtag
class Yeast(Ingredient): using_options(inheritance='multi', polymorphic=True) TYPES = ['ALE', 'LAGER', 'WILD', 'MEAD', 'CIDER', 'WINE'] FORMS = ['DRY', 'LIQUID'] FLOCCULATION_VALUES = [ 'LOW', 'LOW/MEDIUM', 'MEDIUM', 'MEDIUM/HIGH', 'HIGH' ] type = Field(Enum(*TYPES, native_enum=False)) form = Field(Enum(*FORMS, native_enum=False)) attenuation = Field(Float()) flocculation = Field(Enum(*FLOCCULATION_VALUES, native_enum=False)) additions = OneToMany('RecipeAddition', inverse='yeast') def __json__(self): json = super(Yeast, self).__json__() json.update({ 'form': self.form.capitalize(), 'attenuation': self.attenuation }) return json
class Category(Entity): using_options(tablename='category') name = Field(Unicode, primary_key=True) code_sous_cat = Field(Unicode) path = Field(Unicode) url = Field(Unicode) videos = OneToMany('Video') config = ManyToMany('Config', inverse='categories') config_availables = ManyToMany('Config', inverse='categories_availables') def __init__(self, name, dir_user, code_sous_cat, url, create_path=False): self.name = unicode(name) if dir_user: self.path = os.path.join(unicode(dir_user), self.name) self.code_sous_cat = unicode(code_sous_cat) self.url = unicode(url) self.videos = [] if create_path and not os.path.exists(self.path): try: os.makedirs(self.path) except Exception, e: print "%s ne peut être créé" % self.path exit(2)
class known_partners(Entity): id = Field(Integer, primary_key=True) email = Field(String(100), required=True) created = Field(DateTime, default=datetime.now) users = OneToMany('sys_users') using_options(tablename='known_partners') using_table_options(mysql_engine='InnoDB')
class sys_groups(Entity): gid = Field(Integer, primary_key=True) groupname = Field(String(30), required=True) group_password = Field(String(64), required=True) users = OneToMany('sys_users') groupusers = ManyToMany('sys_users', tablename='sys_groupmembers') using_options(tablename='sys_groups') using_table_options(mysql_engine='InnoDB')
class AudiencePosts(Entity): """Mapper for the wp_usermeta entity, the same used by wordpress""" using_options(tablename='wp_posts') id = Field(Integer, primary_key=True, colname='ID') audience = OneToMany('AudiencePostsMeta') def __str__(self): return '<%s "%s">' % ( self.__class__.__name__, self.id) def get_moderated_buzz(self, offset=0, limit=-1, except_ids=[]): """Returns the moderated notice buzz""" except_ids = except_ids or [-1] return Buzz.query \ .filter_by(audience_id=self.id) \ .filter(Buzz.status.in_(['approved', 'selected'])) \ .filter(not_(Buzz.id.in_(except_ids))) \ .order_by(desc('creation_date')) \ .all() def get_public_buzz(self, offset=0, limit=-1, except_ids=[]): """Returns the public notice buzz""" except_ids = except_ids or [-1] query = Buzz.query \ .filter_by(audience_id=self.id) \ .filter(Buzz.status.in_(['inserted'])) \ .filter(not_(Buzz.id.in_(except_ids))) \ .order_by(desc('creation_date')) return limit > 0 and query[offset:limit] or query.all() def get_selected_buzz(self, except_ids=[]): """Returns the selected notice buzz""" except_ids = except_ids or [-1] return Buzz.query \ .filter_by(audience_id=self.id) \ .filter(Buzz.status.in_(['selected'])) \ .filter(not_(Buzz.id.in_(except_ids))) \ .order_by(desc('creation_date')) \ .all() def get_last_published_notice(self): """Returns the last published notice about this audience""" try: return Buzz.query \ .filter_by(audience_id=self.id, status=u'published') \ .order_by(desc('date_published')) \ .first() except NoResultFound: return None def get_all_buzz(self): """Returns the selected notice buzz""" return Buzz.query \ .filter_by(audience_id=self.id) \ .order_by(desc('creation_date')) \ .all()
class Box(Entity): name = Field(UnicodeText) collection = ManyToOne('Collection') collection_index = Field(Integer) cards = OneToMany('Card') using_options(tablename='boxes') using_table_options(schema='inventory')
class DataChecklist(Entity): using_options(tablename='checklists') title = Field(Unicode(255)) items = OneToMany('DataChecklistItem', order_by='index', inverse='checklist', collection_class=ordering_list('index')) card = ManyToOne('DataCard') author = ManyToOne('DataUser') index = Field(Integer) @classmethod def get_by_card(cls, card): q = cls.query q = q.filter_by(card=card) q = q.order_by(cls.index) return q.all() def update(self, other): self.title = other.title self.index = other.index for item in other.items: self.items.append(DataChecklistItem(title=item.title, index=item.index, done=False)) database.session.flush() def __unicode__(self): titles = [item.title for item in self.items if item.title] if self.title: titles.insert(0, self.title) return u'\n'.join(titles) def to_indexable(self): return unicode(self) def add_item_from_str(self, text): item = DataChecklistItem.new_from_str(text) return self.add_item(item) def add_item(self, item): self.items.append(item) return item def insert_item(self, index, item): self.items.insert(index, item) def remove_item(self, item): self.items.remove(item) def delete_item(self, item): self.remove_item(item) item.delete() def purge(self): for item in self.items: item.delete()
class Extra(Ingredient): using_options(inheritance='multi', polymorphic=True) TYPES = ['SPICE', 'FINING', 'WATER AGENT', 'HERB', 'FLAVOR', 'OTHER'] additions = OneToMany('RecipeAddition', inverse='extra') type = Field(Enum(*TYPES, native_enum=False)) liquid = Field(Boolean)
class PlanillaPagos(Entity): using_options(tablename='planilla_pagos') fecha = Field(Date, primary_key=True) barrio = ManyToOne('Barrio', ondelete='cascade', onupdate='cascade', primary_key=True) creditos = OneToMany('PagoCredito') aplicada = Field(Boolean, default=False) def __unicode__(self): return "%s %s" % (self.fecha, self.barrio.nombre) # No uso ColumnProperty para que se refresque automaticamente cuando se modifican los totales @property def total_pagos(self): total = 0 for i in self.creditos: if i.monto: total += i.monto return total class Admin(EntityAdmin): verbose_name = u'Planilla de Pagos' verbose_name_plural = u'Planillas de Pagos' form_display = [ 'fecha', 'barrio', 'creditos', 'total_pagos', ] list_display = ['fecha', 'barrio', 'aplicada'] form_actions = [ BuscarCreditos(), AplicarPlanilla(), ] list_filter = [ ValidDateFilter('fecha', 'fecha', 'Fecha', default=lambda: ''), ComboBoxFilter('barrio.nombre'), ] field_attributes = dict( aplicada=dict(editable=False), creditos=dict(name=u'Créditos'), total_pagos=dict( delegate=CurrencyDelegate, prefix='$', editable=False, name='Total Pagos (f9 para actualizar)', ), ) form_size = (1000, 700) def get_query(self): """Redefino para devolver ordenado por fecha desc""" return EntityAdmin.get_query(self).order_by(desc('fecha'))
class BuzzType(Entity): """Mapper for the `buzztype' entity """ using_options(shortnames=True) name = Field(Unicode(64)) creation_date = Field(DateTime, default=datetime.now) creator = Field(Unicode(64)) buzzes = OneToMany('Buzz') def __str__(self): return self.name
class Strain(Entity): """ 2009-9-22 add 'replicate' into the unique constraint. change type of replicate from boolean to integer """ ecotype = ManyToOne("Ecotype", colname='ecotypeid', ondelete='CASCADE', onupdate='CASCADE') extraction = ManyToOne("Extraction", colname='extractionid', ondelete='CASCADE', onupdate='CASCADE') seqinfo1 = ManyToOne("SeqInfo", colname='seqinfoid1', ondelete='CASCADE', onupdate='CASCADE') seqinfo2 = ManyToOne("SeqInfo", colname='seqinfoid2', ondelete='CASCADE', onupdate='CASCADE') seqinfo3 = ManyToOne("SeqInfo", colname='seqinfoid3', ondelete='CASCADE', onupdate='CASCADE') seqinfo4 = ManyToOne("SeqInfo", colname='seqinfoid4', ondelete='CASCADE', onupdate='CASCADE') plateid = Field(String(25)) wellid = Field(String(3)) replicate = Field(Integer) contaminant_type = ManyToOne("%s.ContaminantType" % __name__, colname='contaminant_type_id', ondelete='CASCADE', onupdate='CASCADE') call_qc_ls = OneToMany("%s.CallQC" % __name__) ecotypeid_strainid2tg_ecotypeid = OneToOne("EcotypeIDStrainID2TGEcotypeID", inverse="strain") created_by = Field(String(128)) updated_by = Field(String(128)) date_created = Field(DateTime, default=datetime.now) date_updated = Field(DateTime) using_options(tablename='strain', metadata=__metadata__, session=__session__) using_table_options(mysql_engine='InnoDB') using_table_options( UniqueConstraint('ecotypeid', 'plateid', 'wellid', 'replicate'))
class Observation(Entity): using_options(tablename='observations') caption = Field(Text, default='Observation') timeBetweenExposuresMin = Field(Integer, default=0) #Seconds! timeBetweenExposuresMax = Field(Integer, default=0) #Seconds! lastExposureAt = Field(DateTime) priority = Field(Integer, default=1000) targetPos = Field(PickleType, required=True) targetName = Field(Text, default='Sky') #(object FITS header) mapRAcount = Field(Integer, default=1) #Map cells along RA mapDECcount = Field(Integer, default=1) #Map cells along DEC mapRAsize = Field(Float, default=2.7777777777777779e-05 ) #Distance between center of cells along RA [deg] mapDECsize = Field(Float, default=2.7777777777777779e-05 ) #Distance between center of cells along DEC [deg] mapLoops = Field(Integer, default=1) #Number of times to loop through map constraints = OneToMany('Constraint', inverse='observation') exposures = OneToMany('Exposure', inverse='observation') program = ManyToOne('Program', inverse='observations')
class Decisao(Entity): id = Field(Integer, primary_key=True, required=True) using_options(tablename='decisao') processo = Field(Integer) tipo = Field(Unicode(45)) proc_classe = Field(Unicode(128)) relator = Field(Unicode(256)) duracao = Field(Integer) origem = Field(Unicode(128)) data_dec = Field(Date) data_pub = Field(Date) UF = Field(Unicode(2)) legislacao = OneToMany('Lei') def __repr__(self): return '<Decisao "%s" (%s)>' % (self.processo, self.data_dec)
class Hop(Ingredient): using_options(inheritance='multi', polymorphic=True) alpha_acid = Field(Float()) origin = Field(Enum(*ORIGINS, native_enum=False)) additions = OneToMany('RecipeAddition', inverse='hop') @property def printed_name(self): return '%s (%s)' % (self.name, self.printed_origin) def __json__(self): json = super(Hop, self).__json__() json.update({'alpha_acid': self.alpha_acid}) return json
class nmap_service(Entity): name = Field(String) product = Field(String) version = Field(String) extrainfo = Field(String) fingerprint = Field(String) port = OneToMany('nmap_port') def __init__(self, name='', product='', version='', extrainfo='', fingerprint=''): self.name = name self.product = product self.version = version self.extrainfo = extrainfo self.fingerprint = fingerprint
class Actividad(Entity): using_options(tablename='actividad') nombre = Field(Unicode(200), unique=True, required=True) amortizacion = ManyToOne('Amortizacion', ondelete='cascade', onupdate='cascade', required=True) rubros = OneToMany('Rubro') class Admin(EntityAdmin): verbose_name = 'Actividad' verbose_name_plural = 'Actividades' list_display = ['nombre', 'amortizacion', 'rubros'] field_attributes = dict(amortizacion=dict(name=u'Amortización'), rubros=dict(admin=RubroAdminEmbedded)) list_search = ['nombre', 'amortizacion.nombre', 'rubros.nombre'] delete_mode = 'on_confirm' def __unicode__(self): return self.nombre or UNDEFINED
class DataChecklist(Entity): using_options(tablename='checklists') title = Field(Unicode(255)) items = OneToMany('DataChecklistItem', order_by='index', inverse='checklist') card = ManyToOne('DataCard') author = ManyToOne('DataUser') index = Field(Integer) def __unicode__(self): titles = [item.title for item in self.items if item.title] if self.title: titles.insert(0, self.title) return u'\n'.join(titles) def reorder_items(self): for i, item in enumerate(self.items): item.index = i
class Fermentable(Ingredient): using_options(inheritance='multi', polymorphic=True) TYPES = ['MALT', 'GRAIN', 'ADJUNCT', 'EXTRACT', 'SUGAR'] type = Field(Enum(*TYPES, native_enum=False)) ppg = Field(Integer) lovibond = Field(Float) origin = Field(Enum(*ORIGINS, native_enum=False)) additions = OneToMany('RecipeAddition', inverse='fermentable') @property def printed_name(self): return '%s (%s)' % (self.name, self.printed_origin) @property def printed_type(self): if self.type is None: return 'Grain' value = self.type.capitalize() if value == 'Malt': value = 'Grain' return value @property def percent_yield(self): return round((self.ppg / 46.00) * 100) def __json__(self): json = super(Fermentable, self).__json__() json.update({ 'ppg': self.ppg, 'lovibond': self.lovibond, 'printed_type': self.printed_type }) return json
class Beneficiaria(Entity): using_options(tablename='beneficiaria') barrio = ManyToOne('Barrio', ondelete='cascade', onupdate='cascade', required=True) nombre = Field(Unicode(200), required=True) apellido = Field(Unicode(200), required=True) grupo = Field(Unicode(200), required=True) fecha_alta = Field(Date, default=datetime.date.today) activa = Field(Boolean, default=True) fecha_baja = Field(Date, nullable=True) comentarios = Field(Unicode(1000), nullable=True) dni = Field(Unicode(10)) fecha_nac = Field(Date) domicilio = Field(Unicode(50)) estado_civil = Field( camelot.types.Enumeration([(0, ''), (1, 'soltera'), (2, 'concubina'), (3, 'casada'), (4, 'separada'), (5, 'divorciada'), (6, 'viuda')])) telefono = Field(Unicode(50)) email = Field(camelot.types.VirtualAddress(256)) default_foto = StoredImage(Storage('fotos', StoredImage), 'sin-foto.jpg') foto = Field(camelot.types.Image(upload_to='fotos'), default=default_foto) creditos = OneToMany('Credito') def _get_activa(self): return self.activa def _set_activa(self, value): # impedir la baja si tiene creditos activos if not value: if self.creditos_activos == 0: fecha_ultimo_pago = sql.select( [sql.func.max(Pago.fecha)], and_(Pago.credito_id == Credito.id, Credito.beneficiaria_id == Beneficiaria.id)) self.fecha_baja = fecha_ultimo_pago self.activa = False else: self.fecha_baja = None self.activa = True _activa = property(_get_activa, _set_activa) @ColumnProperty def creditos_activos(self): return sql.select([sql.func.count(Credito.id)], and_(Credito.beneficiaria_id == Beneficiaria.id, sql.column('fecha_finalizacion') == sql.null())) @ColumnProperty def nombre_completo(self): return self.nombre + ' ' + self.apellido def __unicode__(self): if self.nombre and self.apellido: return '%s %s' % (self.nombre, self.apellido) return UNDEFINED class Admin(EntityAdmin): verbose_name = 'Beneficiaria' delete_mode = 'on_confirm' list_columns_frozen = 1 lines_per_row = 1 # lo especifico por la foto delete_mode = 'on_confirm' list_display = [ 'nombre', 'apellido', 'grupo', 'fecha_alta', '_activa', 'fecha_baja', 'comentarios', 'dni', 'fecha_nac', 'domicilio', 'estado_civil', 'telefono', 'email', 'barrio', ] form_display = TabForm([ ('Beneficiaria', Form([ HBoxForm([[ 'nombre', 'apellido', 'barrio', 'grupo', '_activa', 'fecha_alta', 'fecha_baja', 'comentarios', 'dni', 'fecha_nac', ], [ WidgetOnlyForm('foto'), 'estado_civil', 'domicilio', 'telefono', 'email', 'creditos_activos' ]]) ])), (u'Créditos', WidgetOnlyForm('creditos')), ]) list_filter = [ GroupBoxFilter('activa', default=True), ComboBoxFilter('barrio.nombre'), ] search_all_fields = False list_search = [ 'id', 'nombre_completo', 'comentarios', 'dni', 'grupo', 'barrio.nombre', ] expanded_list_search = [ 'nombre', 'apellido', 'grupo', 'fecha_alta', 'fecha_baja', 'comentarios', 'dni', 'fecha_nac', 'barrio.nombre', ] field_attributes = dict( fecha_alta=dict(name='Fecha Alta'), _activa=dict( name='Activa', delegate=BoolDelegate, # to_string = lambda x:{True:'Si', False:'No'}[x], # TODO no lo toma editable=True, tooltip= u'No se puede dar de baja una beneficiaria si tiene créditos activos.' ), fecha_baja=dict( name='Fecha Baja', tooltip= u'Al desactivar la beneficiaria, este campo toma la última fecha de pago' ), dni=dict(name='DNI'), fecha_nac=dict(name='Fecha Nac.'), estado_civil=dict(name='Estado Civil'), telefono=dict(name=u'Teléfono'), email=dict(address_type='email'), creditos=dict(admin=CreditoAdminEmbedded), creditos_activos=dict(name=u'Créditos activos', editable=False), ) form_size = (850, 400)
class DataBoard(Entity): """Board mapper - ``title`` -- board title - ``columns`` -- list of board columns - ``labels`` -- list of labels for cards - ``comments_allowed`` -- who can comment ? (0 nobody, 1 board members only , 2 all application users) - ``votes_allowed`` -- who can vote ? (0 nobody, 1 board members only , 2 all application users) - ``description`` -- board description - ``visibility`` -- board visibility (0 Private, 1 Public) - ``members`` -- list of members (simple members and manager) - ``managers`` -- list of managers - ``uri`` -- board URI (Universally Unique IDentifier) - ``last_users`` -- list of last users - ``pending`` -- invitations pending for new members (use token) - ``archive`` -- display archive column ? (0 false, 1 true) - ``archived`` -- is board archived ? """ using_options(tablename='board') title = Field(Unicode(255)) columns = OneToMany('DataColumn', order_by="index", cascade='delete') labels = OneToMany('DataLabel', order_by='index') comments_allowed = Field(Integer, default=1) votes_allowed = Field(Integer, default=1) description = Field(UnicodeText, default=u'') visibility = Field(Integer, default=0) version = Field(Integer, default=0, server_default='0') board_members = OneToMany('DataBoardMember', cascade='delete') board_managers = OneToMany('DataBoardManager', cascade='delete') members = AssociationProxy('board_members', 'member', creator=lambda member: DataBoardMember(member=member)) managers = AssociationProxy('board_managers', 'member', creator=lambda member: DataBoardManager(member=member)) uri = Field(Unicode(255), index=True, unique=True) last_users = ManyToOne('DataUser', order_by=('fullname', 'email')) pending = OneToMany('DataToken', order_by='username') history = OneToMany('DataHistory') background_image = Field(Unicode(255)) background_position = Field(Unicode(255)) title_color = Field(Unicode(255)) archive = Field(Integer, default=0) archived = Field(Boolean, default=False) weighting_cards = Field(Integer, default=0) weights = Field(Unicode(255), default=u'') def delete_members(self): for member in self.board_members: session.delete(member) session.flush() def delete_history(self): for event in self.history: session.delete(event) session.flush() def increase_version(self): self.version += 1 if self.version > 2147483600: self.version = 1 @property def url(self): return urllib.quote_plus( "%s/%s" % (self.title.encode('ascii', 'ignore'), self.uri), '/' ) def __init__(self, *args, **kwargs): """Initialization. Create board and uri of the board """ super(DataBoard, self).__init__(*args, **kwargs) self.uri = unicode(uuid.uuid4()) def label_by_title(self, title): """Return a label instance which match with title In: - ``title`` -- the title of the label to search for Return: - label instance """ return (l for l in self.labels if l.title == title).next() @classmethod def get_by_id(cls, id): return cls.get(id) @classmethod def get_by_uri(cls, uri): return cls.query.filter_by(uri=uri).first() def has_member(self, user): """Return True if user is member of the board In: - ``user`` -- user to test (User instance) Return: - True if user is member of the board """ return user.data in self.members def remove_member(self, board_member): board_member.delete() def has_manager(self, user): """Return True if user is manager of the board In: - ``user`` -- user to test (User instance) Return: - True if user is manager of the board """ return user.data in self.managers def remove_manager(self, board_member): obj = DataBoardManager.query.filter_by(board=self, member=board_member.get_user_data()).first() if obj is not None: obj.delete() self.remove_member(board_member) def change_role(self, board_member, new_role): obj = DataBoardManager.query.filter_by(board=self, member=board_member.get_user_data()).first() if new_role == 'manager': if obj is None: obj = DataBoardManager(board=self, member=board_member.get_user_data()) session.add(obj) else: if obj is not None: obj.delete() def last_manager(self, member): """Return True if member is the last manager of the board""" return member.role == 'manager' and len(self.managers) == 1 def add_member(self, new_member, role='member'): """ Add new member to the board In: - ``new_member`` -- user to add (DataUser instance) - ``role`` -- role's member (manager or member) """ self.board_members.append(DataBoardMember(member=new_member.data)) if role == 'manager': self.managers.append(new_member.data) session.flush() def get_pending_users(self): emails = [token.username for token in self.pending] return DataUser.query.filter(DataUser.email.in_(emails)) def set_background_image(self, image): self.background_image = image or u'' @classmethod def get_last_modified_boards_for(cls, user_username, user_source): q2 = session.query(DataHistory.board_id.distinct()) q2 = q2.filter(DataHistory.user_username == user_username) q2 = q2.filter(DataHistory.user_source == user_source) q2 = q2.order_by(DataHistory.when.desc()) q2 = q2.limit(5) q = cls.query.distinct().join(DataBoardMember) q = q.filter(DataBoardMember.user_username == user_username) q = q.filter(DataBoardMember.user_source == user_source) q = q.filter(DataBoard.id.in_(q2)) q = q.filter(cls.archived == False) return q @classmethod def get_user_boards_for(cls, user_username, user_source): q = cls.query.join(DataBoardManager) q = q.filter(DataBoardManager.user_username == user_username) q = q.filter(DataBoardManager.user_source == user_source) q = q.filter(cls.archived == False) q = q.order_by(DataBoard.title) return q @classmethod def get_guest_boards_for(cls, user_username, user_source): q2 = session.query(DataBoardManager.board_id) q2 = q2.filter(DataBoardManager.user_username == user_username) q2 = q2.filter(DataBoardManager.user_source == user_source) q = cls.query.join(DataBoardMember) q = q.filter(DataBoardMember.user_username == user_username) q = q.filter(DataBoardMember.user_source == user_source) q = q.filter(cls.archived == False) q = q.filter(~DataBoard.id.in_(q2)) q = q.order_by(DataBoard.title) return q @classmethod def get_archived_boards_for(cls, user_username, user_source): q = cls.query.join(DataBoardMember) q = q.filter(DataBoardMember.user_username == user_username) q = q.filter(DataBoardMember.user_source == user_source) q = q.filter(cls.archived == True) q = q.order_by(DataBoard.title) return q
class DataColumn(Entity): """Column mapper """ using_options(tablename='column') title = Field(Unicode(200)) index = Field(Integer) nb_max_cards = Field(Integer) archive = Field(Boolean, default=False) cards = OneToMany( 'DataCard', order_by='index', # cascade='delete', collection_class=ordering_list('index'), lazy='subquery') board = ManyToOne('DataBoard', colname='board_id') def update(self, other): self.title = other.title self.index = other.index self.nb_max_cards = other.nb_max_cards session.flush() @classmethod def create_column(cls, board, index, title, nb_cards=None, archive=False): """Create new column In: - ``board`` -- DataBoard, father of the column - ``index`` -- position in the board - ``title`` -- title of the column Return: - created DataColumn instance """ q = cls.query q = q.filter(cls.index >= index) q = q.filter(cls.board == board) q.update({'index': cls.index + 1}) col = cls(title=title, index=index, board=board, nb_max_cards=nb_cards, archive=archive) # session.add(col) session.flush() return col def create_card(self, title, user): card = DataCard(title=title, creation_date=datetime.now()) self.cards.append(card) session.flush() return card def remove_card(self, card): if card in self.cards: self.cards.remove(card) def insert_card(self, index, card): done = False if card not in self.cards: self.cards.insert(index, card) session.flush() done = True return done def delete_card(self, card): self.remove_card(card) card.delete() def purge_cards(self): for card in self.cards: card.delete() def append_card(self, card): done = False if card not in self.cards: card.index = None self.cards.append(card) session.flush() done = True return done @classmethod def delete_column(cls, column): """Delete column Delete a given column, re-index other columns and delete all cards of the column In: - ``column`` -- DataColumn instance to delete """ index = column.index board = column.board column.delete() session.flush() q = cls.query q = q.filter(cls.index >= index) q = q.filter(cls.board == board) q.update({'index': cls.index - 1}) def get_cards_count(self): q = DataCard.query.filter(DataCard.column_id == self.id) return q.with_entities(func.count()).scalar()
class DataMembership(Entity): using_options(tablename='membership') board = ManyToOne('DataBoard', ondelete='cascade', required=True) user = ManyToOne(DataUser, ondelete='cascade', required=True) card_memberships = OneToMany(DataCardMembership, cascade='delete, delete-orphan') # provisional, for notifications until they are refactored cards = association_proxy('card_memberships', 'card') manager = Field(Boolean, default=False, nullable=False) notify = Field(Integer, default=NOTIFY_MINE) using_table_options( sa.UniqueConstraint('board_id', 'user_username', 'user_source', name='membership_ix')) @classmethod def get_for_card(cls, card): return cls.query.join(DataCardMembership).filter( DataCardMembership.card == card) @classmethod def search(cls, board, user): return cls.get_by(board=board, user=user) # at most one @classmethod def subscribers(cls): return cls.query.filter( sa.or_(DataMembership.notify == NOTIFY_ALL, DataMembership.notify == NOTIFY_MINE)) @staticmethod def favorites_for(card): query = database.session.query(DataUser) query = query.join(DataMembership) # In the future, cards will be linked to boards directly, so demeter won't be hurt anymore query = query.filter(DataMembership.board == card.column.board) query = query.outerjoin(DataCardMembership) query = query.group_by(DataUser) query = query.order_by(func.count(DataUser.username).desc()) return query @classmethod def add_card_members_from_emails(cls, card, emails): """Provisional: will take memberships instead of emails.""" query = cls.query.join(DataUser).filter( sa.or_(DataUser.email.in_(emails), DataUser.email_to_confirm.in_(emails)), DataMembership.board == card.column.board) memberships = query.all() for membership in memberships: membership.card_memberships.append(DataCardMembership(card=card)) database.session.flush() return memberships @classmethod def remove_card_member(cls, card, username): """Provisional: will take a membership instead of username.""" membership = cls.query.join(DataUser).filter( DataUser.username == username, cls.board == card.column.board).first() if membership: card_membership = DataCardMembership.get_by(card=card, membership=membership) if card_membership: card_membership.delete() @classmethod def add_member(cls, board, user, manager=False): membership = cls(board=board, user=user, manager=manager) database.session.add(membership) database.session.flush() return membership @classmethod def remove_member(cls, board, user): membership = cls.get_by(board=board, user=user) if membership: membership.delete() database.session.flush() @classmethod def has_member(cls, board, user, manager=False): membership = cls.get_by(board=board, user=user) return (bool(membership) and membership.manager) if manager else bool(membership) @classmethod def delete_members(cls, board): cls.query.filter_by(board=board).delete(synchronize_session=False) @classmethod def change_role(cls, board, user, manager): ms = cls.get_by(board=board, user=user) if ms: ms.manager = manager database.session.flush()
class Paragrafo(Entity): id = Field(Unicode(64), primary_key=True) conteudo = Field(Unicode) comentario = OneToMany('Comentario')
class Credito(Entity): using_options(tablename='credito') beneficiaria = ManyToOne('Beneficiaria', ondelete='cascade', onupdate='cascade', required=True) rubro = ManyToOne('Rubro', ondelete='cascade', onupdate='cascade', required=True) fecha_entrega = Field(Date, required=True) fecha_cobro = Field(Date, required=True) prestamo = Field(Float) saldo_anterior = Field(Float) monto_cheque = Field(Float) tasa_interes = Field(Float(precision=5)) deuda_total = Field(Float) cartera = ManyToOne('Cartera', ondelete='cascade', onupdate='cascade', required=True) cuotas = Field(Integer, required=True) nro_credito = Field(Integer, default=0, required=True) fecha_finalizacion = Field(Date) comentarios = Field(Unicode(1000)) gastos_arq = Field(Float) pagos = OneToMany('Pago') def _get_fecha_entrega(self): return self.fecha_entrega def _set_fecha_entrega(self, fecha): self.fecha_entrega = fecha self.fecha_cobro = fecha + datetime.timedelta(days=2) _fecha_entrega = property(_get_fecha_entrega, _set_fecha_entrega) def _deuda_aleman(self): factor = self.tasa_interes / 24 cuota = self.prestamo / self.cuotas deuda_ant = self.prestamo deuda = 0 for i in range(1, self.cuotas): deuda += cuota + factor * deuda_ant deuda_ant -= cuota return deuda + self.gastos_arq def _update_deuda_total(self): if self.para_construccion: self.deuda_total = self._deuda_aleman() else: self.deuda_total = self.prestamo * (1 + self.tasa_interes) def _update_monto_cheque(self): self.monto_cheque = self.prestamo - self.saldo_anterior def _get_prestamo(self): return self.prestamo def _set_prestamo(self, value): self.prestamo = value self._update_monto_cheque() self._update_deuda_total() _prestamo = property(_get_prestamo, _set_prestamo) def _get_saldo_anterior(self): return self.saldo_anterior def _set_saldo_anterior(self, value): self.saldo_anterior = value self._update_monto_cheque() _saldo_anterior = property(_get_saldo_anterior, _set_saldo_anterior) def _get_tasa_interes(self): return self.tasa_interes def _set_tasa_interes(self, value): self.tasa_interes = value self._update_deuda_total() _tasa_interes = property(_get_tasa_interes, _set_tasa_interes) @ColumnProperty def barrio(self): return sql.select([Barrio.nombre], and_(Credito.beneficiaria_id == Beneficiaria.id, Beneficiaria.barrio_id == Barrio.id)) # tbl_credito = Credito.mapper.mapped_table # tbl_barrio = Barrio.mapper.mapped_table # tbl_benef = Beneficiaria.mapper.mapped_table # return sql.select([tbl_barrio.c.nombre], # from_obj = tbl_credito.join(tbl_benef).join(tbl_barrio), # whereclause = tbl_credito.c.id == self.id) @ColumnProperty def activo(self): return sql.select([sql.column('fecha_finalizacion') == sql.null()]) # No uso ColumnProperty para que se refresque automaticamente cuando se modifican los totales @property def total_pagos(self): total = 0 for i in self.pagos: total += i.monto return total # agrego esta property para poder ordenar y filtrar por este campo @ColumnProperty def beneficiaria_prop(self): return sql.select( [sql.func.concat(Beneficiaria.nombre, ' ', Beneficiaria.apellido)], Credito.beneficiaria_id == Beneficiaria.id) # agrego esta property para poder ordenar y filtrar por este campo @ColumnProperty def rubro_prop(self): return sql.select([Rubro.nombre], Credito.rubro_id == Rubro.id) @property def para_construccion(self): if self.rubro: return self.rubro.actividad_id == ID_ACTIVIDAD_CONSTRUCCION return False @property def saldo(self): if self.total_pagos: return self.deuda_total - self.total_pagos else: return self.deuda_total def __unicode__(self): if self.beneficiaria or self.nro_credito: return '%s %s (cred. #%s)' % (self.beneficiaria.nombre, self.beneficiaria.apellido, self.nro_credito) return UNDEFINED class Admin(CreditoAdminBase): pass
class A1(Entity): using_options(resolve_root='tests.db1') a2s = OneToMany('A2') bs = ManyToMany('b.B')