I am struggling in creating a recursive method to automate record creation in Odoo. I request the WSDL of a SOAP service and process it until I receive the following string:
{'notificaCertificadoRevocado':{
'input': {
'SolicitudNotificaRevocado':{
'optional': False,
'type': {
'certificado': {
'optional': False,
'type': 'String(value)'
},
'codigoAmbiente': {
'optional': False,
'type': 'Int(value)'
}
}
}
}
}
}
This dictionary has 1 parent parameter "SolicitudNotificaRevocado" and 2 child parameters "certificado" and "codigoAmbiente".
My python method by the moment looks like this:
def _prepare_parameter_list(self, parameter_dict, recursive_data=False):
building_data = recursive_data if recursive_data else {}
parameter_list = []
for key, value in parameter_dict.items():
if key != 'optional' and key != 'type':
# Create parameters
parameter_name_dict = {
'name': key,
'description': ' '.join(word.capitalize() for word in camel_case_split(key)),
}
characterization_dict = self._prepare_parameter_list(value)
built_parameter_dict = {**parameter_name_dict, **characterization_dict}
parameter_list.append((0, 0, built_parameter_dict))
# TODO: Here the code stops
return parameter_list
else:
if key == 'optional':
building_data = {**building_data, **{'optional': value}}
if key == 'type':
if isinstance(value, dict):
building_data = {**building_data, **{'parameter_ids': self._prepare_parameter_list(value)}}
else:
building_data = {**building_data, **{'type': value.split('(')[0]}}
return building_data
This is working pretty good with only one problem, the data that is being returned has the following form:
[(0, 0, {
'name': 'SolicitudOperacionesCuis',
'description': 'Solicitud Operaciones Cuis',
'optional': False,
'parameter_ids': [
(0, 0, {
'name': 'codigoAmbiente',
'description': 'Codigo Ambiente',
'optional': False,
'type': 'Int'})]
})
]
The problem is that the method after processing one of the child parameters stops because of the "return parameter_list" part. (I have even added a TODO comment in the problem part) I would like to retrieve the following data:
[(0, 0, {
'name': 'SolicitudOperacionesCuis',
'description': 'Solicitud Operaciones Cuis',
'optional': False,
'parameter_ids': [
(0, 0, {
'name': 'certificado',
'description': 'Certificado',
'optional': False,
'type': 'String'})]
}),
(0, 0, {
'name': 'codigoAmbiente',
'description': 'Codigo Ambiente',
'optional': False,
'type': 'Int'})]
})
]
How should I tweak my method to achieve this? Working with recursive methods is hard!
CodePudding user response:
In the end I took a different approach refactoring the method drastically. Because my previous code had an additional problem. If checking the previous desired output:
[(0, 0, {
'name': 'SolicitudOperacionesCuis',
'description': 'Solicitud Operaciones Cuis',
'optional': False,
'parameter_ids': [
(0, 0, {
'name': 'certificado',
'description': 'Certificado',
'optional': False,
'type': 'String'})]
}),
(0, 0, {
'name': 'codigoAmbiente',
'description': 'Codigo Ambiente',
'optional': False,
'type': 'Int'})]
})
]
There is a nested One2many record creation that Odoo does not recognize. Anyway, since I was not able to make the previous code to work, I started creating records individually:
def _create_parameters(self, process_object, parameter_id=False, parent_parameter_id=False):
for key, value in process_object.items():
if key != 'optional' and key != 'type':
try:
soap_parameter = self.env['soap.parameter'].search([
'&', '&', '&', '&',
['active', '=', True],
['name', '=', key],
['description', '=', ' '.join(word.capitalize() for word in camel_case_split(key))],
['method_id', '=', self.id],
['parent_id', '=', parent_parameter_id]
], limit=1)[0]
except IndexError:
# Create parameters
soap_parameter = self.env['soap.parameter'].create({
'name': key,
'description': ' '.join(word.capitalize() for word in camel_case_split(key)),
'method_id': self.id,
'parent_id': parent_parameter_id
})
self._create_parameters(value, soap_parameter, soap_parameter.id)
if parameter_id:
if key == 'optional':
parameter_id.write({'optional': value})
if key == 'type':
if isinstance(value, dict):
self._create_parameters(value, parent_parameter_id=parent_parameter_id)
else:
value_type = value.split('(')[0]
if value_type == 'Int':
value_type = 'int'
elif value_type == 'String':
value_type = 'str'
elif value_type == 'Long':
value_type = 'float'
parameter_id.write({'type': value_type})
This code would search and update or create my parameters.
CodePudding user response:
If the input data is already known and it seems the useful data is the one in the input dictionary, then you don't need the recursion element. Updated a similar function below that outputs your expected output
def _prepare_parameter_list(parameter_dict):
def _return_data_type(value_type):
if value_type == 'Int':
value_type = 'int'
elif value_type == 'String':
value_type = 'str'
elif value_type == 'Long':
value_type = 'float'
return value_type
parent = parameter_dict.get('notificaCertificadoRevocado')
building_data = []
if parent and parent.get('input'):
for key, value in parent['input']:
vals = {
'name': key,
'description': ' '.join(word.capitalize() for word in camel_case_split(key)),
'optional': value.get('optional'),
}
parameter_ids = []
if value.get('type'):
for par_key, par_value in value['type']:
pams = {
'name': par_key,
'description': par_key.capitalize(),
'optional': par_value.get('optional'),
'type': par_value.get('type') and _return_data_type(par_value['type'].split('(')[0]) or False,
}
parameter_ids.append((0, 0, pams))
vals.update(parameter_ids=parameter_ids)
building_data.append((0, 0, vals))
return building_data