class UOM(orm.BaseExpando): _kind = 72 _use_rule_engine = False measurement = orm.SuperStringProperty('1', required=True, indexed=False) name = orm.SuperStringProperty('2', required=True, indexed=False) symbol = orm.SuperStringProperty('3', required=True, indexed=False) rate = orm.SuperDecimalProperty('4', required=True, indexed=False) factor = orm.SuperDecimalProperty('5', required=True, indexed=False) rounding = orm.SuperDecimalProperty('6', required=True, indexed=False) digits = orm.SuperIntegerProperty('7', required=True, indexed=False) _default_indexed = False _expando_fields = { 'code': orm.SuperStringProperty('8', required=True), 'numeric_code': orm.SuperStringProperty('9'), 'grouping': orm.SuperIntegerProperty('10', repeated=True), 'decimal_separator': orm.SuperStringProperty('11', required=True), 'thousands_separator': orm.SuperStringProperty('12'), 'positive_sign_position': orm.SuperIntegerProperty('13', required=True), 'negative_sign_position': orm.SuperIntegerProperty('14', required=True), 'positive_sign': orm.SuperStringProperty('15'), 'negative_sign': orm.SuperStringProperty('16'), 'positive_currency_symbol_precedes': orm.SuperBooleanProperty('17', default=True), 'negative_currency_symbol_precedes': orm.SuperBooleanProperty('18', default=True), 'positive_separate_by_space': orm.SuperBooleanProperty('19', default=True), 'negative_separate_by_space': orm.SuperBooleanProperty('20', default=True) }
class TestB(orm.BaseModel): _use_memcache = False _use_cache = False _use_record_engine = False _use_rule_engine = False _use_search_engine = False name = orm.SuperStringProperty() gaa = orm.SuperIntegerProperty()
class Line(orm.BaseExpando): '''Notes: We always seqence lines that have debit > 0, and after them come lines that have credit > 0 In case that Entry.balanced=True, sum of all debit amounts must eqal to sum of all credit amounts. To make instances of lines, you must always provide parent key, that is entry's key. Otherwise it will break! Fields can only be properly loaded if are: - loaded from datastore - instanced with proper keyword argument Entry (journal or _model_schema) and Line (parent) ''' _kind = 51 _use_rule_engine = False _journal_fields_loaded = None # Expando # Some queries on Line require "join" with Entry. # That problem can be solved using search engine (or keeping some entry field values copied to lines)! #journal = orm.SuperKeyProperty('1', kind=Journal, required=True) # delete #company = orm.SuperKeyProperty('2', kind='44', required=True) # delete #state = orm.SuperIntegerProperty('3', required=True) # delete #date = orm.SuperDateTimeProperty('4', required=True) # delete sequence = orm.SuperIntegerProperty('5', required=True) categories = orm.SuperKeyProperty('6', kind='47', repeated=True) debit = orm.SuperDecimalProperty('7', required=True, indexed=False) # debit = 0 in case that credit > 0, negative values are forbidden. credit = orm.SuperDecimalProperty('8', required=True, indexed=False) # credit = 0 in case that debit > 0, negative values are forbidden. uom = orm.SuperLocalStructuredProperty(uom.UOM, '9', required=True) def __init__(self, *args, **kwargs): '''Caution! Making instances of Line() inside a transaction may cause performing non-entity group queries (see in add journal fields). As for get()s itself it will use in-memory cache when it can. ''' entry_key = kwargs.get('parent') complete_key = kwargs.get('key') # Also observe the complete key instances. journal_key = kwargs.pop('journal', None) # if journal key is provided use it. This is generally retarded but only way so far. if journal_key is not None: self.add_journal_fields(journal_key) elif entry_key is not None: self.add_journal_fields(entry_key.entity.journal) elif complete_key is not None: self.add_journal_fields(complete_key.parent_entity.journal) # we intentionally call this code before __init__ due __init__ ability to deepcopy the entity and other things beside that. super(Line, self).__init__(*args, **kwargs) def add_journal_fields(self, journal_key=None): if not self._journal_fields_loaded: if not journal_key and self.key: journal_key = self.parent_entity.journal journal = journal_key.get() if journal is None: raise Exception('Cannot find journal with key %r.' % journal_key) self._clone_properties() for name, prop in journal.line_fields.iteritems(): # still not 100% sure if we need to deepcopy these properties that get loaded from datastore prop._code_name = name self._properties[prop._name] = prop self.add_output(name) self._journal_fields_loaded = True def get_kind(self): return '%s_%s' % (self._get_kind(), self.journal.id()) def get_fields(self): fields = super(Line, self.__class__).get_fields() # Calling parent get_fields. for name, prop in self._properties.iteritems(): fields[prop._code_name] = prop return fields def _get_property_for(self, p, indexed=True, depth=0): '''It is always easier to override _get_property_for because you immidiately get self which tells you on which entity you operate, and if the entity itself has a key. ''' if self.key is None or self.key.parent() is None: raise Exception('Cannot load properties of %s because it does not have parent key provided.' % self) else: if self._journal_fields_loaded is None: self.add_journal_fields() return super(Line, self)._get_property_for(p, indexed, depth) @classmethod def get_meta(cls): '''This function returns dictionary of meta data (not stored or dynamically generated data) of the model. The returned dictionary can be transalted into other understandable code to clients (e.g. JSON). ''' dic = {} dic['_actions'] = getattr(cls, '_actions', []) dic.update(super(Line, cls).get_fields()) return dic
''' from google.appengine.ext.ndb.google_imports import entity_pb from app import orm, settings from app.models import uom from app.models.base import * from app.plugins.base import * from app.plugins.transaction import * defaults1 = () defaults2 = ('required',) JOURNAL_FIELDS = ((orm.SuperStringProperty(), defaults1, defaults2), (orm.SuperTextProperty(), defaults1, defaults2), (orm.SuperIntegerProperty(), defaults1, defaults2), (orm.SuperFloatProperty(), defaults1, defaults2), (orm.SuperDecimalProperty(), defaults1, defaults2), (orm.SuperBooleanProperty(), defaults1, defaults2), (orm.SuperJsonProperty(), defaults1, defaults2), (orm.SuperKeyProperty(), defaults1, defaults2), (orm.SuperDateTimeProperty(), defaults1, defaults2)) class Action(orm.Action): _kind = 84 _use_rule_engine = False arguments = orm.SuperPropertyStorageProperty('2', required=True, default={}, compressed=False, cfg=JOURNAL_FIELDS) @classmethod def build_key(cls, *args, **kwargs):
class Widget(orm.BaseExpando): _kind = 62 _use_search_engine = True # @todo This is extra added for testing functions of google seach! name = orm.SuperStringProperty( '1', required=True, searchable=True ) # @todo This is extra added for testing functions of google seach! sequence = orm.SuperIntegerProperty( '2', required=True, searchable=True ) # @todo This is extra added for testing functions of google seach! active = orm.SuperBooleanProperty( '3', required=True, default=True, searchable=True ) # @todo This is extra added for testing functions of google seach! role = orm.SuperKeyProperty('4', kind='60', required=True) search_form = orm.SuperBooleanProperty('5', required=True, indexed=False, default=True) filters = orm.SuperLocalStructuredProperty(Filter, '6', repeated=True) _default_indexed = False _virtual_fields = {'_records': orm.SuperRecordProperty('62')} _global_role = GlobalRole(permissions=[ orm.ActionPermission( '62', [ orm.Action.build_key('62', 'prepare'), orm.Action.build_key('62', 'create'), orm.Action.build_key('62', 'read'), orm.Action.build_key('62', 'update'), orm.Action.build_key('62', 'delete'), orm.Action.build_key('62', 'search'), orm.Action.build_key('62', 'build_menu') ], False, 'entity._original.namespace_entity._original.state != "active"'), orm.ActionPermission('62', [ orm.Action.build_key('62', 'create'), orm.Action.build_key('62', 'update'), orm.Action.build_key('62', 'delete') ], False, 'entity._is_system'), orm.FieldPermission( '62', [ 'name', 'sequence', 'active', 'role', 'search_form', 'filters', '_records' ], False, False, 'entity._original.namespace_entity._original.state != "active"'), orm.FieldPermission('62', [ 'name', 'sequence', 'active', 'role', 'search_form', 'filters', '_records' ], False, None, 'entity._is_system'), orm.FieldPermission( '62', ['role'], False, None, '(action.key_id_str == "create" or action.key_id_str == "update") and (entity.role and entity.role._namespace != entity._original.key_namespace)' ) ]) _actions = [ orm.Action(key=orm.Action.build_key('62', 'prepare'), arguments={ 'domain': orm.SuperKeyProperty(kind='6', required=True) }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), RulePrepare(), RuleExec(), Set(cfg={'d': { 'output.entity': '_widget' }}) ]) ]), orm.Action( key=orm.Action.build_key('62', 'create'), arguments={ 'domain': orm.SuperKeyProperty(kind='6', required=True), 'name': orm.SuperStringProperty(required=True), 'sequence': orm.SuperIntegerProperty(required=True), 'active': orm.SuperBooleanProperty(default=True), 'role': orm.SuperKeyProperty(kind='60', required=True), 'search_form': orm.SuperBooleanProperty(default=True), 'filters': orm.SuperLocalStructuredProperty(Filter, repeated=True) }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), Set( cfg={ 'd': { '_widget.name': 'input.name', '_widget.sequence': 'input.sequence', '_widget.active': 'input.active', '_widget.role': 'input.role', '_widget.search_form': 'input.search_form', '_widget.filters': 'input.filters' } }), RulePrepare(), RuleExec() ]), orm.PluginGroup( transactional=True, plugins=[ Write(), Set(cfg={'d': { 'output.entity': '_widget' }}), CallbackNotify(), CallbackExec() ]) ]), orm.Action(key=orm.Action.build_key('62', 'read'), arguments={ 'key': orm.SuperKeyProperty(kind='62', required=True), 'read_arguments': orm.SuperJsonProperty() }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), RulePrepare(), RuleExec(), Set(cfg={'d': { 'output.entity': '_widget' }}) ]) ]), orm.Action( key=orm.Action.build_key('62', 'update'), arguments={ 'key': orm.SuperKeyProperty(kind='62', required=True), 'name': orm.SuperStringProperty(required=True), 'sequence': orm.SuperIntegerProperty(required=True), 'active': orm.SuperBooleanProperty(default=True), 'role': orm.SuperKeyProperty(kind='60', required=True), 'search_form': orm.SuperBooleanProperty(default=True), 'filters': orm.SuperLocalStructuredProperty(Filter, repeated=True), 'read_arguments': orm.SuperJsonProperty() }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), Set( cfg={ 'd': { '_widget.name': 'input.name', '_widget.sequence': 'input.sequence', '_widget.active': 'input.active', '_widget.role': 'input.role', '_widget.search_form': 'input.search_form', '_widget.filters': 'input.filters' } }), RulePrepare(), RuleExec() ]), orm.PluginGroup( transactional=True, plugins=[ Write(), Set(cfg={'d': { 'output.entity': '_widget' }}), CallbackNotify(), CallbackExec() ]) ]), orm.Action( key=orm.Action.build_key('62', 'delete'), arguments={'key': orm.SuperKeyProperty(kind='62', required=True)}, _plugin_groups=[ orm.PluginGroup( plugins=[Context( ), Read(), RulePrepare(), RuleExec()]), orm.PluginGroup( transactional=True, plugins=[ Delete(), Set(cfg={'d': { 'output.entity': '_widget' }}), CallbackNotify(), CallbackExec() ]) ]), orm.Action( key=orm.Action.build_key('62', 'search'), arguments={ 'domain': orm.SuperKeyProperty(kind='6', required=True), 'search': orm.SuperSearchProperty( default={ 'filters': [], 'orders': [{ 'field': 'sequence', 'operator': 'asc' }] }, cfg={ 'use_search_engine': True, # @todo This is extra added for testing functions of google seach! 'search_arguments': { 'kind': '62', 'options': { 'limit': settings.SEARCH_PAGE } }, 'filters': { 'name': orm.SuperStringProperty(), 'role': orm.SuperKeyProperty(kind='60'), 'active': orm.SuperBooleanProperty() }, 'orders': { 'name': { 'default_value': { 'asc': 'a', 'desc': 'z' } }, # @todo This is extra added for testing functions of google seach! 'sequence': { 'default_value': { 'asc': 0, 'desc': 1000000 } } }, # @todo This is extra added for testing functions of google seach! 'indexes': [{ 'orders': [('name', ['asc', 'desc'])] }, { 'orders': [('sequence', ['asc', 'desc'])] }, { 'filters': [('name', ['==', '!='])], 'orders': [('sequence', ['asc', 'desc'])] }, { 'filters': [('active', ['=='])], 'orders': [('sequence', ['asc', 'desc'])] }, { 'filters': [('role', ['==', '!='])], 'orders': [('sequence', ['asc', 'desc'])] }, { 'filters': [('active', ['==']), ('name', ['==', '!='])], 'orders': [('sequence', ['asc', 'desc'])] }, { 'filters': [('active', ['==']), ('role', ['==', '!='])], 'orders': [('sequence', ['asc', 'desc'])] }] }) }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), RulePrepare(), RuleExec(), Search(), RulePrepare(cfg={'path': '_entities'}), Set( cfg={ 'd': { 'output.entities': '_entities', 'output.cursor': '_cursor', 'output.more': '_more' } }) ]) ]), orm.Action(key=orm.Action.build_key('62', 'build_menu'), arguments={ 'domain': orm.SuperKeyProperty(kind='6', required=True) }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), RulePrepare(), RuleExec(), WidgetBuildMenu(), Set( cfg={ 'd': { 'output.menu': '_widgets', 'output.domain': 'domain' } }) ]) ]) ] @property def _is_system(self): return self.key_id_str.startswith('system_')
class Unit(orm.BaseExpando): _kind = 19 _use_record_engine = False _use_cache = True _use_memcache = True measurement = orm.SuperStringProperty( '1', required=True ) # By definition, once a unit is created, measurement can not be modified! @todo We can implement choices=['Currency', 'Mass'...], or we can use query projections for data presentation from this property! Shall we incorporate measurement value into key_id? name = orm.SuperStringProperty('2', required=True) symbol = orm.SuperStringProperty('3', required=True, indexed=False) rate = orm.SuperDecimalProperty( '4', indexed=False ) # The coefficient for the formula: 1 (base unit) = coef (this unit) - digits=(12, 12). factor = orm.SuperDecimalProperty( '5', indexed=False ) # The coefficient for the formula: coef (base unit) = 1 (this unit) - digits=(12, 12). rounding = orm.SuperDecimalProperty( '6', indexed=False) # Rounding Precision - digits=(12, 12). digits = orm.SuperIntegerProperty('7', indexed=False) active = orm.SuperBooleanProperty('8', required=True, default=True) _default_indexed = False _expando_fields = { 'code': orm.SuperStringProperty('9'), 'numeric_code': orm.SuperStringProperty('10'), 'grouping': orm.SuperIntegerProperty('11', repeated=True), 'decimal_separator': orm.SuperStringProperty('12'), 'thousands_separator': orm.SuperStringProperty('13'), 'positive_sign_position': orm.SuperIntegerProperty('14'), 'negative_sign_position': orm.SuperIntegerProperty('15'), 'positive_sign': orm.SuperStringProperty('16'), 'negative_sign': orm.SuperStringProperty('17'), 'positive_currency_symbol_precedes': orm.SuperBooleanProperty('18', default=True), 'negative_currency_symbol_precedes': orm.SuperBooleanProperty('19', default=True), 'positive_separate_by_space': orm.SuperBooleanProperty('20', default=True), 'negative_separate_by_space': orm.SuperBooleanProperty('21', default=True) } _global_role = GlobalRole(permissions=[ orm.ActionPermission('19', [ orm.Action.build_key('19', 'update_currency'), orm.Action.build_key('19', 'update_unit') ], True, 'user._root_admin or user._is_taskqueue'), orm.ActionPermission('19', [orm.Action.build_key('19', 'search')], True, 'not user._is_guest'), orm.FieldPermission('19', [ 'measurement', 'name', 'symbol', 'rate', 'factor', 'rounding', 'digits', 'active', 'code', 'numeric_code', 'grouping', 'decimal_separator', 'thousands_separator', 'positive_sign_position', 'negative_sign_position', 'positive_sign', 'positive_currency_symbol_precedes', 'negative_currency_symbol_precedes', 'positive_separate_by_space', 'negative_separate_by_space' ], False, True, 'True'), orm.FieldPermission('19', [ 'measurement', 'name', 'symbol', 'rate', 'factor', 'rounding', 'digits', 'active', 'code', 'numeric_code', 'grouping', 'decimal_separator', 'thousands_separator', 'positive_sign_position', 'negative_sign_position', 'positive_sign', 'positive_currency_symbol_precedes', 'negative_currency_symbol_precedes', 'positive_separate_by_space', 'negative_separate_by_space' ], True, True, 'user._root_admin or user._is_taskqueue') ]) _actions = [ orm.Action(key=orm.Action.build_key('19', 'update_currency'), arguments={}, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), RulePrepare(cfg={'skip_user_roles': True}), RuleExec(), UnitCurrencyUpdateWrite( cfg={'file': settings.CURRENCY_DATA_FILE}) ]) ]), orm.Action( key=orm.Action.build_key('19', 'update_unit'), arguments={}, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), RulePrepare(cfg={'skip_user_roles': True}), RuleExec(), UnitUpdateWrite(cfg={'file': settings.UOM_DATA_FILE}) ]) ]), orm.Action( key=orm.Action.build_key('19', 'search'), arguments={ 'search': orm.SuperSearchProperty( default={ 'filters': [{ 'field': 'active', 'value': True, 'operator': '==' }], 'orders': [{ 'field': 'name', 'operator': 'asc' }] }, cfg={ 'search_by_keys': True, 'search_arguments': { 'kind': '19', 'options': { 'limit': 1000 } }, 'filters': { 'measurement': orm.SuperStringProperty(), 'active': orm.SuperBooleanProperty(choices=[True]) }, 'indexes': [{ 'filters': [('active', ['=='])], 'orders': [('name', ['asc', 'desc'])] }, { 'filters': [('active', ['==']), ('measurement', ['=='])], 'orders': [('name', ['asc', 'desc'])] }] }) }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), RulePrepare(cfg={'skip_user_roles': True}), RuleExec(), Search(), UnitRemoveCurrencies( ), # @todo This will be probably be removed!! RulePrepare(cfg={ 'path': '_entities', 'skip_user_roles': True }), Set( cfg={ 'd': { 'output.entities': '_entities', 'output.cursor': '_cursor', 'output.more': '_more' } }) ]) ]) ] # @todo Do we make this a property named _uom or something similar ? def get_uom(self): '''This is because using unit_key.get() does not guarantee fresh new instance of unit that can be referenced as a entity, thats why we always create new instance of UOM. ''' new_uom = UOM() uom_fields = UOM.get_fields() for field_key, field in uom_fields.iteritems(): setattr(new_uom, field_key, getattr(self, field_key)) return new_uom