Why do I get this error?: Expected singleton: spray.action(1, 2) - odoo-10

I have a button in a form that when clicked is supposed to update the current model mrl with data from the spray.action model. Then I do further processing but it raises the error
ValueError("Expected singleton: %s" % self) ValueError: Expected singleton: spray.action(1, 2)
#api.multi
def mrlCreateSprayRecords(self):
spray_ids = []
vals = []
spray_obj = self.env['spray.action'].search([])
print("spray_obj \n\n\n\t %s ", spray_obj)
for obj in spray_obj:
print("Spray Action Objects \n\n %s \n\t ", obj)
vals = {
'ref': obj.ref,
'farm': obj.farm.farm,
'block': obj.block.block,
'valves': obj.valves.valve,
}
print("Spray Action Data Browse , \n\n\t %s ", vals)
res = super(Mrl, self).create(vals)
res.update(vals)
print("object in mrlCreateSprayRecords \n\n\t %s", res)
return {
'name': 'Update Mrl Operations',
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'form',
'res_model': 'mrl',
'views': [(spray_obj.id, 'form')],
'view_id': spray_obj.id,
# 'target': 'new',
'res_id': self.id,
'context': self.env.context,
}

I think you are getting the error in the row 'view_id': spray_obj.id, you must write the view id there. The spray_obj recordset has many record, so you cannot use it like that (spray_obj.id). You can also remove the view_id parameter in order to user the default view.
#api.multi
def mrlCreateSprayRecords(self):
self.ensure_one()
spray_obj = self.env['spray.action'].search([]) # recordset of all records of the model????
for obj in spray_obj:
vals = {
'ref': obj.ref,
'farm': obj.farm.farm,
'block': obj.block.block,
'valves': obj.valves.valve,
}
self.create(vals)
view_id = self.env.ref('module.xml_view_id').id
return {
'name': 'Update Mrl Operations',
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'form',
'res_model': 'mrl',
'view_id': view_id,
'res_id': self.id,
'context': self.env.context,
}
I have added self.ensure_one() because res_id has to be only one id as well.
I have remove the res.update(vals) line because it does not make any sense to me haha
More things
Instead of print you should use the logger:
import logging
_logger = logging.getLogger(__name__)
_logger.info('Hello')
Instead the line res = super(Mrl, self).create(vals) I think you should use this one
res = self.create(vals) # if you are in the mrl model

In short you get this kind of error when you acces a field direclty of a recordSet that contains more than one record.
You performed a search on the spray.action that search returnd 2 record (1, 2)
So when you do spray_obj.id odoo will be confused what id he should return 1 or 2. And here odoo throw this error.
So dont access a field a search result, or a x2many fiels they may have more than one record inside.
#ChesuCR has improved your code and corrected it

Related

Use one of the two incoming observable stream to filter data in angular

I have the below code I have the formcontrol value (its a multicheckbox list), the values is an array of true/false, [true, false, true, true, ...]. This is one of the many lists
I also have the data list - collection of objects of structure {id: number, desc: string, disabled: boolean, selected: boolean}
I need to retrieve the id matching the true by matching index, and set an observable
I have the below code
valueChanged(e: any, name: string, key: string, valuesArray: string) {
this.hasChanged = true;
from(name).pipe(
debounceTime(200),
withLatestFrom(this[name].value), // this[name] is form array, gives [true, false, false,..]
mergeMap(values => forkJoin(
of(values),
this[valuesArray].find(val => val.name === name).data
)),
mergeMap(([values, data]) => {
flatMap((val, i) => val ? data[i].id : null),
filter(id => id !== null),
map(ids => {
this.selectedFilters[key] = ids;
switch (key) {
case 'groupId':
this.curGroup.next(ids);
break;
}
});
})
);
}
I need help on the line flatmap where I want to use values, for each of the value (true/false), if val[i] is true, include data[i].id in the output i want he id array of true values [1,2,4,5,..]. I get the error
Argument of type '([values, data]: [[string, unknown], unknown]) => void' is not assignable to parameter of type '(value: [[string, unknown], unknown], index: number) => ObservableInput'.
Type 'void' is not assignable to type 'ObservableInput'.ts(2345)
Need help on how to use solve this issue. Thanks in advance.

Return view with activated filter in Odoo

I'm trying to return a tree view in Odoo filtered by a parameter. Some one knows how to code the variable my_context of the view?
I need to apply the filter with the field: father_competence_id
The filter is defined as:
<filter name="groupby_fathercompetence"
context="{'group_by' : 'father_competence_id'}"
string="Father competence" />
academic_record_lines = self.env['education.record']
for line in self:
academic_record_lines = academic_record_lines + line.env['education.record'].search([('n_line_id', '=', line.id)])
return {
'name': _('Academic records for {} [{}]').format(
description, self.planification_id.teacher_id.name),
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'education.record',
'type': 'ir.actions.act_window',
'context': **my_context**,
'domain': [('id', 'in', academic_record_lines.ids)],
}
Please use the below code
my_context = dict(self._context or {})
my_context.update({'':})
Using my_context.update you can add filters through context.
return {
'name': _('Academic records for {} [{}]').format(
description, self.planification_id.teacher_id.name),
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'education.record',
'type': 'ir.actions.act_window',
'context': my_context,
'domain': [('id', 'in', academic_record_lines.ids)],
}
If you know the filter name, which is normally set by attribute name on the search <filter> entries, you can automatically activate them by an action by providing the filter name with search_default_ in front of it and as value a truthy value like True or 1.
academic_record_lines = self.env['education.record'].search(
[('n_line_id', 'in', self.ids)])
context = dict(self.env.context or {})
context['search_default_groupby_fathercompetence'] = True
return {
# self.pla... only working with singleton!!!
'name': _('Academic records for {} [{}]').format(
description, self.planification_id.teacher_id.name),
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'education.record',
'type': 'ir.actions.act_window',
'context': context,
'domain': [('id', 'in', academic_record_lines.ids)],
}

openerp7 - Return tree view from class with no new fields

I'm new to OpenERP 7, what is the correct way to return a tree view? How can i return the data i obtained from my function?
Here's my class code:
class albaranes_fallidos(osv.osv):
_name = 'albaranes_fallidos'
_inherit = 'stock.picking'
_columns = {}
def find(self, cr, uid, ids, context=None):
stock_picking = self.pool.get('stock.picking')
exist_state = stock_picking.search(cr, uid, [('state','=','confirmed'),('origin','ilike','SO')])
###
exist_lines = stock_picking.browse(cr, uid, exist_state, context)
###
exist_IN = stock_picking.search(cr, uid, [('type','=','in'),('origin','ilike',':SO')])
for SO in exist_lines:
exist_PO = stock_picking.browse(cr, uid, exist_IN, context)
for POSO in exist_PO:
if SO.origin in POSO.origin:
_logger.info(POSO.origin)
break
You need to use a domain to specify which record to load in tree view:
return {
'type': 'ir.actions.act_window',
'name': _('Stock picking'),
'res_model': 'stock.picking',
'view_type': 'form',
'view_mode': 'tree,form',
'target': 'current',
'domain': [('id', 'in', exist_IN)]
}

Odoo8 - Need a example of ir.actions.server executing multiple actions one after the other

In a wizzard view I have a button returning pdf report in a 'ir.action.act_url'. It works fine. Problem is that after the pdf appeared I would like the wizzard window to be closed automatically. To do this I can return close_window dict.
Separately this two 'return' work fine.
I would like to execute two actions, one after another. I found that this is possible using ir.action.server with multi attribute.
Unfortunately I couldn't find even one example.
close_window = {'type': 'ir.actions.act_window_close'}
final_report = {
'type': 'ir.actions.act_url',
'url': '/web/binary/saveas?model=ir.attachment&field=datas&
filename_field=name&id=' + str(file.id),
'target': 'self',
}
return final_report
Check the ir_actions tests that ship with Odoo, they might be able to help you in the right direction.
base/tests/test_ir_actions.py
def test_60_multi(self):
cr, uid = self.cr, self.uid
# Data: 2 server actions that will be nested
act1_id = self.ir_actions_server.create(cr, uid, {
'name': 'Subaction1',
'sequence': 1,
'model_id': self.res_partner_model_id,
'state': 'code',
'code': 'action = {"type": "ir.actions.act_window"}',
})
act2_id = self.ir_actions_server.create(cr, uid, {
'name': 'Subaction2',
'sequence': 2,
'model_id': self.res_partner_model_id,
'state': 'object_create',
'use_create': 'copy_current',
})
act3_id = self.ir_actions_server.create(cr, uid, {
'name': 'Subaction3',
'sequence': 3,
'model_id': self.res_partner_model_id,
'state': 'code',
'code': 'action = {"type": "ir.actions.act_url"}',
})
self.ir_actions_server.write(cr, uid, [self.act_id], {
'state': 'multi',
'child_ids': [(6, 0, [act1_id, act2_id, act3_id])],
})
# Do: run the action
res = self.ir_actions_server.run(cr, uid, [self.act_id], context=self.context)
# Test: new partner created
pids = self.res_partner.search(cr, uid, [('name', 'ilike', 'TestingPartner (copy)')]) # currently res_partner overrides default['name'] whatever its value
self.assertEqual(len(pids), 1, 'ir_actions_server: TODO')
# Test: action returned
self.assertEqual(res.get('type'), 'ir.actions.act_url')
# Test loops
with self.assertRaises(except_orm):
self.ir_actions_server.write(cr, uid, [self.act_id], {
'child_ids': [(6, 0, [self.act_id])]
})
Have not done it myself, but it looks like you have to specify that it is a multi action, and specify the child_ids actions to be executed.
Also keep in mind that according to the docs (https://www.odoo.com/documentation/8.0/reference/actions.html):
multi
Executes multiple actions one after the other. Actions to execute are
defined via the child_ids m2m. If sub-actions themselves return
actions, the last one will be returned to the client as the multi's
own next action
According to #dgeorgiev I wrote further code. I managed to create server actions and individually this actions are able to return pdf file or close the window. But I couldn't combine these two return's. See below:
# first server action returning pdf
ir_actions_server = self.env['ir.actions.server']
act1_id = ir_actions_server.create({
'type': 'ir.actions.server',
'name': 'divided_package_labels',
'sequence': 1,
'model_id': self.id,
'state': 'code',
'code': 'action = {"type": "ir.actions.act_url", "url": "/web/binary/saveas?model=ir.attachment&field=datas&filename_field=name&id= %s", "target": "new"}' % str(file.id),
})
# second server action closing window
act2_id = ir_actions_server.create({
'type': 'ir.actions.server',
'name': 'Close_sale.package.wizard',
'sequence': 2,
'model_id': self.id,
'state': 'code',
'code': 'action = {"type": "ir.actions.act_window_close"}'
})
# server action for combining two previously described
act_id = ir_actions_server.create({
'type': 'ir.actions.server',
'name': 'TestAction',
'condition': 'True',
'model_id': self.id,
'state': 'multi',
# 'child_ids': [(6, 0, [act1_id.id])] # return pdf
# 'child_ids': [(6, 0, [act2_id.id])] # close window
'child_ids': [(6, 0, [act1_id.id, act2_id.id])] # close window, no pdf file
})
print act_id, act1_id, act2_id
print "act_id.child_ids", act_id.child_ids
# shows that the relations are properly made
# run
return act_id.run()
Probably there is a small mistake, but I couldn't find it.

Ruby SQL Server and Do blocks

I have the following code:
sql = "select Board_Name AS 'Board Name', COUNT(Board_Name) AS 'Count' from dbo.TABLE GROUP BY Board_Name"
result = client.execute(sql)
result.each do |row|
binfo = [ label: row['Board Name'], value: row['Count'] ]
send_event('ticketsbyboard', { items: binfo })
end
I'm trying to get all of the rows passed to the send_event as one array, instead of just one row at a time.
Try a map:
binfo = result.map do |row|
{ label: row['Board Name'], value: row['Count'] }
end
send_event('ticketsbyboard', { items: binfo })
If your result object doesn't respond directly to map, just use result.to_a.map

Resources