Package Camelot :: Package camelot :: Package model :: Module type_and_status
[frames] | no frames]

Source Code for Module Camelot.camelot.model.type_and_status

  1  ''' 
  2   
  3  Created on Sep 25, 2009 
  4   
  5  @author: Erik De Rijcke 
  6   
  7  ''' 
  8  import datetime 
  9   
 10  from elixir.entity import Entity, EntityMeta 
 11   
 12  from sqlalchemy.types import Date, Unicode 
 13  from sqlalchemy.sql import and_ 
 14   
 15  from elixir.fields import Field 
 16  from elixir.options import using_options 
 17  from elixir.relationships import ManyToOne, OneToMany 
 18   
 19  from camelot.model.authentication import end_of_times 
 20  from camelot.view.elixir_admin import EntityAdmin 
 21  from camelot.types import Code, Enumeration 
 22   
 23  # 
 24  # Global dict keeping track of which status class is used for which class 
 25  # 
 26  __status_classes__ = {} 
27 28 -def get_status_class(cls_name):
29 """ 30 :param cls_name: an Entity class name 31 :return: the status class used for this entity 32 """ 33 return __status_classes__[cls_name]
34
35 -def create_type_3_status_mixin(status_attribute):
36 """Create a class that can be subclassed to provide a class that 37 has a type 3 status with methods to manipulate and review its status 38 :param status_attribute: the name of the type 3 status attribute 39 """ 40 41 class Type3StatusMixin(object): 42 43 @property 44 def current_status(self): 45 classified_by = None 46 today = datetime.date.today() 47 for status_history in self.status: 48 if status_history.status_from_date<=today and status_history.status_thru_date>=today: 49 classified_by = status_history.classified_by 50 return classified_by
51 52 def change_status(self, new_status, status_from_date=None, status_thru_date=end_of_times()): 53 from sqlalchemy import orm 54 if not status_from_date: 55 status_from_date = datetime.date.today() 56 mapper = orm.class_mapper(self.__class__) 57 status_property = mapper.get_property('status') 58 status_type = status_property._get_target().class_ 59 old_status = status_type.query.filter( and_( status_type.status_for == self, 60 status_type.status_from_date <= status_from_date, 61 status_type.status_thru_date >= status_from_date ) ).first() 62 if old_status != None: 63 old_status.thru_date = datetime.date.today() - datetime.timedelta( days = 1 ) 64 old_status.status_thru_date = status_from_date - datetime.timedelta( days = 1 ) 65 new_status = status_type( status_for = self, 66 classified_by = new_status, 67 status_from_date = status_from_date, 68 status_thru_date = status_thru_date, 69 from_date = datetime.date.today(), 70 thru_date = end_of_times() ) 71 if old_status: 72 self.query.session.flush( [old_status] ) 73 self.query.session.flush( [new_status] ) 74 75 return Type3StatusMixin 76
77 -def type_3_status( statusable_entity, metadata, collection, verbose_entity_name = None, enumeration=None ):
78 ''' 79 Creates a new type 3 status related to the given entity 80 :statusable_entity: A string referring to an entity. 81 :enumeration: if this parameter is used, no status type Entity is created, but the status type is 82 described by the enumeration. 83 ''' 84 t3_status_name = statusable_entity + '_status' 85 t3_status_type_name = statusable_entity + '_status_type' 86 87 88 if not enumeration: 89 90 class Type3StatusTypeMeta( EntityMeta ): 91 def __new__( cls, classname, bases, dictionary ): 92 return EntityMeta.__new__( cls, t3_status_type_name, 93 bases, dictionary )
94 def __init__( self, classname, bases, dictionary ): 95 EntityMeta.__init__( self, t3_status_type_name, 96 bases, dictionary ) 97 98 class Type3StatusType( Entity, ): 99 using_options( tablename = t3_status_type_name.lower(), metadata=metadata, collection=collection ) 100 __metaclass__ = Type3StatusTypeMeta 101 102 code = Field( Code( parts = ['>AAAA'] ), index = True, 103 required = True, unique = True ) 104 description = Field( Unicode( 40 ), index = True ) 105 106 def __unicode__( self ): 107 return 'Status type: %s : %s' % ( '.'.join( self.code ), self.description ) 108 109 class Admin( EntityAdmin ): 110 list_display = ['code', 'description'] 111 verbose_name = statusable_entity + ' Status Type' 112 if verbose_entity_name is not None: 113 verbose_name = verbose_entity_name + ' Status Type' 114 115 class Type3StatusMeta( EntityMeta ): 116 def __new__( cls, classname, bases, dictionary ): 117 return EntityMeta.__new__( cls, t3_status_name, 118 bases, dictionary ) 119 def __init__( self, classname, bases, dictionary ): 120 EntityMeta.__init__( self, t3_status_name, 121 bases, dictionary ) 122 123 class Type3Status( Entity, ): 124 """ 125 Status Pattern 126 .. attribute:: status_datetime For statuses that occur at a specific point in time 127 .. attribute:: status_from_date For statuses that require a date range 128 .. attribute:: from_date When a status was enacted or set 129 """ 130 using_options( tablename = t3_status_name.lower(), metadata=metadata, collection=collection ) 131 __metaclass__ = Type3StatusMeta 132 133 status_datetime = Field( Date, required = False ) 134 status_from_date = Field( Date, required = False ) 135 status_thru_date = Field( Date, required = False ) 136 from_date = Field( Date, required = True, default = datetime.date.today ) 137 thru_date = Field( Date, required = True, default = end_of_times ) 138 139 status_for = ManyToOne( statusable_entity, #required = True, 140 ondelete = 'cascade', onupdate = 'cascade' ) 141 142 if not enumeration: 143 classified_by = ManyToOne( t3_status_type_name, required = True, 144 ondelete = 'cascade', onupdate = 'cascade' ) 145 else: 146 classified_by = Field(Enumeration(enumeration), required=True, index=True) 147 148 class Admin( EntityAdmin ): 149 verbose_name = statusable_entity + ' Status' 150 verbose_name_plural = statusable_entity + ' Statuses' 151 list_display = ['status_from_date', 'status_thru_date', 'classified_by'] 152 verbose_name = statusable_entity + ' Status' 153 if verbose_entity_name is not None: 154 verbose_name = verbose_entity_name + ' Status' 155 156 def __unicode__( self ): 157 return u'Status' 158 159 __status_classes__[statusable_entity] = Type3Status 160 161 return t3_status_name 162
163 -def entity_type( typable_entity, metadata, collection, verbose_entity_name = None ):
164 ''' 165 Creates a new type related to the given entity. 166 .. typeable_entity:: A string referring to an entity. 167 ''' 168 type_name = typable_entity + '_type' 169 170 class TypeMeta( EntityMeta ): 171 def __new__( cls, classname, bases, dictionary ): 172 return EntityMeta.__new__( cls, type_name, 173 bases, dictionary )
174 def __init__( self, classname, bases, dictionary ): 175 EntityMeta.__init__( self, type_name, 176 bases, dictionary ) 177 178 class Type( Entity ): 179 using_options( tablename = type_name.lower(), metadata=metadata, collection=collection ) 180 __metaclass__ = TypeMeta 181 182 type_description_for = OneToMany( typable_entity ) 183 description = Field( Unicode( 48 ), required = True ) 184 185 class Admin( EntityAdmin ): 186 verbose_name = typable_entity + ' Type' 187 list_display = ['description', ] 188 verbose_name = typable_entity + ' Type' 189 if verbose_entity_name is not None: 190 verbose_name = verbose_entity_name + ' Type' 191 192 def __unicode__( self ): 193 return u'Type: %s' % ( self.description ) 194 195 return type_name 196