SAP interface: easy access to SAP results. Bugfix in search method.
This commit is contained in:
parent
e89eda4838
commit
2ff08258bc
|
@ -194,6 +194,7 @@ class ArchetypeFieldDescriptor:
|
||||||
# field is invisible; we will display it ourselves (like for Ref fields)
|
# field is invisible; we will display it ourselves (like for Ref fields)
|
||||||
|
|
||||||
alwaysAValidatorFor = ('Ref', 'Integer', 'Float')
|
alwaysAValidatorFor = ('Ref', 'Integer', 'Float')
|
||||||
|
notToValidateFields = ('Info', 'Computed', 'Action')
|
||||||
def walkAppyType(self):
|
def walkAppyType(self):
|
||||||
'''Walks into the Appy type definition and gathers data about the
|
'''Walks into the Appy type definition and gathers data about the
|
||||||
Archetype elements to generate.'''
|
Archetype elements to generate.'''
|
||||||
|
@ -233,13 +234,15 @@ class ArchetypeFieldDescriptor:
|
||||||
# - slaves ?
|
# - slaves ?
|
||||||
if self.appyType.slaves: self.widgetParams['visible'] = False
|
if self.appyType.slaves: self.widgetParams['visible'] = False
|
||||||
# Archetypes will believe the field is invisible; we will display it
|
# Archetypes will believe the field is invisible; we will display it
|
||||||
# ourselves (like for Ref fields)
|
# ourselves (like for Ref fields).
|
||||||
# - need to generate a field validator?
|
# - need to generate a field validator?
|
||||||
# In all cases, add an i18n message for the validation error for this
|
# In all cases excepted for "immutable" fields, add an i18n message for
|
||||||
# field.
|
# the validation error for this field.
|
||||||
label = '%s_%s_valid' % (self.classDescr.name, self.fieldName)
|
if self.appyType.type not in self.notToValidateFields:
|
||||||
poMsg = PoMessage(label, '', PoMessage.DEFAULT_VALID_ERROR)
|
label = '%s_%s_valid' % (self.classDescr.name, self.fieldName)
|
||||||
self.generator.labels.append(poMsg)
|
poMsg = PoMessage(label, '', PoMessage.DEFAULT_VALID_ERROR)
|
||||||
|
self.generator.labels.append(poMsg)
|
||||||
|
# Generate a validator for the field if needed.
|
||||||
if (type(self.appyType.validator) == types.FunctionType) or \
|
if (type(self.appyType.validator) == types.FunctionType) or \
|
||||||
(type(self.appyType.validator) == type(String.EMAIL)) or \
|
(type(self.appyType.validator) == type(String.EMAIL)) or \
|
||||||
(self.appyType.type in self.alwaysAValidatorFor):
|
(self.appyType.type in self.alwaysAValidatorFor):
|
||||||
|
|
|
@ -124,7 +124,8 @@ class ToolMixin(AbstractMixin):
|
||||||
useful for some usages like knowing the number of objects without
|
useful for some usages like knowing the number of objects without
|
||||||
needing to get information about them). If no p_maxResults is
|
needing to get information about them). If no p_maxResults is
|
||||||
specified, the method returns maximum
|
specified, the method returns maximum
|
||||||
self.getNumberOfResultsPerPage(). p_maxResults is ignored if
|
self.getNumberOfResultsPerPage(). The method returns all objects if
|
||||||
|
p_maxResults equals string "NO_LIMIT". p_maxResults is ignored if
|
||||||
p_brainsOnly is True.'''
|
p_brainsOnly is True.'''
|
||||||
# Is there one or several content types ?
|
# Is there one or several content types ?
|
||||||
if contentType.find(',') != -1:
|
if contentType.find(',') != -1:
|
||||||
|
@ -164,6 +165,7 @@ class ToolMixin(AbstractMixin):
|
||||||
brains = self.portal_catalog.searchResults(**params)
|
brains = self.portal_catalog.searchResults(**params)
|
||||||
if brainsOnly: return brains
|
if brainsOnly: return brains
|
||||||
if not maxResults: maxResults = self.getNumberOfResultsPerPage()
|
if not maxResults: maxResults = self.getNumberOfResultsPerPage()
|
||||||
|
elif maxResults == 'NO_LIMIT': maxResults = None
|
||||||
res = SomeObjects(brains, maxResults, startNumber)
|
res = SomeObjects(brains, maxResults, startNumber)
|
||||||
res.brainsToObjects()
|
res.brainsToObjects()
|
||||||
# In some cases (p_remember=True), we need to keep some information
|
# In some cases (p_remember=True), we need to keep some information
|
||||||
|
|
|
@ -197,7 +197,14 @@ class AbstractMixin:
|
||||||
history, for example).'''
|
history, for example).'''
|
||||||
# Which value will we use ?
|
# Which value will we use ?
|
||||||
if useParamValue: v = value
|
if useParamValue: v = value
|
||||||
else: v = eval('self.%s' % name)
|
else:
|
||||||
|
try:
|
||||||
|
v = eval('self.%s' % name)
|
||||||
|
except AttributeError:
|
||||||
|
# Probably a newly created attribute.
|
||||||
|
# In this case, return the default value.
|
||||||
|
v = None
|
||||||
|
if appyType: v = appyType['default']
|
||||||
if not appyType: return v
|
if not appyType: return v
|
||||||
if (v == None) or (v == ''): return v
|
if (v == None) or (v == ''): return v
|
||||||
vType = appyType['type']
|
vType = appyType['type']
|
||||||
|
|
|
@ -98,7 +98,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div metal:define-macro="showInfoField">
|
<div metal:define-macro="showInfoField">
|
||||||
<span class="appyLabel" tal:content="label"></span>
|
<span class="appyLabel" tal:content="structure label"></span>
|
||||||
<span tal:content="structure description"></span>
|
<span tal:content="structure description"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -102,6 +102,9 @@ class AbstractWrapper:
|
||||||
key = self.o.workflow_history.keys()[0]
|
key = self.o.workflow_history.keys()[0]
|
||||||
return self.o.workflow_history[key]
|
return self.o.workflow_history[key]
|
||||||
history = property(get_history)
|
history = property(get_history)
|
||||||
|
def get_user(self):
|
||||||
|
return self.o.portal_membership.getAuthenticatedMember()
|
||||||
|
user = property(get_user)
|
||||||
|
|
||||||
def link(self, fieldName, obj):
|
def link(self, fieldName, obj):
|
||||||
'''This method links p_obj to this one through reference field
|
'''This method links p_obj to this one through reference field
|
||||||
|
@ -270,6 +273,10 @@ class AbstractWrapper:
|
||||||
contentType = flavour.o.getPortalType(klass)
|
contentType = flavour.o.getPortalType(klass)
|
||||||
# Create the Search object
|
# Create the Search object
|
||||||
search = Search('customSearch', sortBy=sortBy, **fields)
|
search = Search('customSearch', sortBy=sortBy, **fields)
|
||||||
|
if not maxResults:
|
||||||
|
maxResults = 'NO_LIMIT'
|
||||||
|
# If I let maxResults=None, only a subset of the results will be
|
||||||
|
# returned by method executeResult.
|
||||||
res = self.tool.o.executeQuery(contentType,flavour.number,search=search,
|
res = self.tool.o.executeQuery(contentType,flavour.number,search=search,
|
||||||
maxResults=maxResults)
|
maxResults=maxResults)
|
||||||
return [o.appy() for o in res['objects']]
|
return [o.appy() for o in res['objects']]
|
||||||
|
|
|
@ -32,6 +32,27 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
hasSap = False
|
hasSap = False
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
class SapResult:
|
||||||
|
'''Represents a result as returned by SAP. It defines a __getattr__ method
|
||||||
|
that allows to retrieve SAP "output" parameters (export, tables) by their
|
||||||
|
name (as if they were attributes of this class), in a Python format
|
||||||
|
(list, dict, simple value).'''
|
||||||
|
def __init__(self, function):
|
||||||
|
# The pysap function obj that was called and that produced this result.
|
||||||
|
self.function = function
|
||||||
|
def __getattr__(self, name):
|
||||||
|
'''Allows a smart access to self.function's results.'''
|
||||||
|
if name.startswith('__'): raise AttributeError
|
||||||
|
paramValue = self.function[name]
|
||||||
|
paramType = paramValue.__class__.__name__
|
||||||
|
if paramType == 'ItTable':
|
||||||
|
return paramValue.to_list()
|
||||||
|
elif paramType == 'STRUCT':
|
||||||
|
return paramValue.to_dict()
|
||||||
|
else:
|
||||||
|
return paramValue
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class Sap:
|
class Sap:
|
||||||
'''Represents a remote SAP system. This class allows to connect to a distant
|
'''Represents a remote SAP system. This class allows to connect to a distant
|
||||||
|
@ -43,6 +64,7 @@ class Sap:
|
||||||
self.user = user
|
self.user = user
|
||||||
self.password = password
|
self.password = password
|
||||||
self.sap = None # Will hold the handler to the SAP distant system.
|
self.sap = None # Will hold the handler to the SAP distant system.
|
||||||
|
self.functionName = None # The name of the next function to call.
|
||||||
if not hasSap: raise SapError(SAP_MODULE_ERROR)
|
if not hasSap: raise SapError(SAP_MODULE_ERROR)
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
|
@ -84,9 +106,11 @@ class Sap:
|
||||||
res[name.lower()] = v
|
res[name.lower()] = v
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def call(self, functionName, **params):
|
def call(self, functionName=None, **params):
|
||||||
'''Calls a function on the SAP server.'''
|
'''Calls a function on the SAP server.'''
|
||||||
try:
|
try:
|
||||||
|
if not functionName:
|
||||||
|
functionName = self.functionName
|
||||||
function = self.sap.get_interface(functionName)
|
function = self.sap.get_interface(functionName)
|
||||||
# Specify the parameters
|
# Specify the parameters
|
||||||
for name, value in params.iteritems():
|
for name, value in params.iteritems():
|
||||||
|
@ -118,6 +142,14 @@ class Sap:
|
||||||
function()
|
function()
|
||||||
except pysap.BaseSapRfcError, se:
|
except pysap.BaseSapRfcError, se:
|
||||||
raise SapError(SAP_FUNCTION_ERROR % (functionName, str(se)))
|
raise SapError(SAP_FUNCTION_ERROR % (functionName, str(se)))
|
||||||
|
return SapResult(function)
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
'''The user can directly call self.<sapFunctionName>(params) instead of
|
||||||
|
calling self.call(<sapFunctionName>, params).'''
|
||||||
|
if name.startswith('__'): raise AttributeError
|
||||||
|
self.functionName = name
|
||||||
|
return self.call
|
||||||
|
|
||||||
def getTypeInfo(self, typeName):
|
def getTypeInfo(self, typeName):
|
||||||
'''Returns information about the type (structure) named p_typeName.'''
|
'''Returns information about the type (structure) named p_typeName.'''
|
||||||
|
|
Loading…
Reference in a new issue