This is the original method but I want to call it with super and ad my context to it, but it's old API and I'm kinda confused here.
After move_scrap write method should be called, but nothing happens and write is not called
and with_context of course not working
class stock_move_scrap(osv.osv_memory):
_name = "stock.move.scrap"
_description = "Scrap Products"
def move_scrap(self, cr, uid, ids, context=None):
""" To move scrapped products
#param self: The object pointer.
#param cr: A database cursor
#param uid: ID of the user currently logged in
#param ids: the ID or list of IDs if we want more than one
#param context: A standard dictionary
#return:
"""
if context is None:
context = {}
move_obj = self.pool.get('stock.move')
move_ids = context['active_ids']
for data in self.browse(cr, uid, ids):
move_obj.action_scrap(cr, uid, move_ids,
data.product_qty, data.location_id.id, restrict_lot_id=data.restrict_lot_id.id,
context=context)
if context.get('active_id'):
move = self.pool.get('stock.move').browse(cr, uid, context['active_id'], context=context)
if move.picking_id:
return {
'view_type': 'form',
'view_mode': 'form',
'res_model': 'stock.picking',
'type': 'ir.actions.act_window',
'res_id': move.picking_id.id,
'context': context
}
return {'type': 'ir.actions.act_window_close'}
i did try something like this
def move_scrap(self, cr, uid, ids, context=None):
if context is None:
context = {}
ctx = context.copy()
ctx['allow_scrap'] = True
super(stock_move_scrap,self).move_scrap(cr, uid, [], context=ctx)
Your issue is that you are removing the ids from the super call by replacing the expected ids arg with [].
Change you last line from:
super(stock_move_scrap,self).move_scrap(cr, uid, [], context=ctx)
to:
super(stock_move_scrap,self).move_scrap(cr, uid, ids, context=ctx)
Related
In Odoo 10, is it possible to define a report to list the purchase orders marked as confirmed but not sent by email to supplier?
i.e., how can I detect if in a purchase order the action "sent PO by email" was completed or not.
Thanks,
You can do it using following simple way.
Step 1 : Add one boolean field in Purchase order model and update context in following method.
from odoo import fields,models,api
class purchase_order(models.Model):
_inherit="purchase.order"
sent_po_via_email=fields.Boolean("Sent PO Via Email",default=False,copy=False)
#api.multi
def action_rfq_send(self):
'''
This function opens a window to compose an email, with the edi purchase template message loaded by default
'''
self.ensure_one()
ctx = dict(self.env.context or {})
ir_model_data = self.env['ir.model.data']
try:
if self.env.context.get('send_rfq', False):
template_id = ir_model_data.get_object_reference('purchase', 'email_template_edi_purchase')[1]
else:
ctx.update({'sent_po_via_email':True})
template_id = ir_model_data.get_object_reference('purchase', 'email_template_edi_purchase_done')[1]
except ValueError:
template_id = False
try:
compose_form_id = ir_model_data.get_object_reference('mail', 'email_compose_message_wizard_form')[1]
except ValueError:
compose_form_id = False
ctx.update({
'default_model': 'purchase.order',
'default_res_id': self.ids[0],
'default_use_template': bool(template_id),
'default_template_id': template_id,
'default_composition_mode': 'comment',
})
return {
'name': _('Compose Email'),
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'form',
'res_model': 'mail.compose.message',
'views': [(compose_form_id, 'form')],
'view_id': compose_form_id,
'target': 'new',
'context': ctx,
}
we have override action_rfq_send method & check if user is not sending ref then update context ctx.update({'sent_po_via_email':True}).
Step 2: Inherit send_mail method of mail.compose.message.
class MailComposeMessage(models.TransientModel):
_inherit = 'mail.compose.message'
#api.multi
def send_mail(self, auto_commit=False):
context = self._context
if context.get('default_model') == 'purchase.order' and \
context.get('default_res_id') and context.get('sent_po_via_email'):
po_order = self.env['purchase.order'].browse(context['default_res_id'])
po_order.sent_po_via_email = True
return super(MailComposeMessage, self).send_mail(auto_commit=auto_commit)
In above method we have checked if user is sending purchase order via email then set check mark True.
We have used simple context to identify process & based on the context, write a value in purchase order.
Try this:
Inherit purchase.order' model and add aBoolean field`.
Write True to this Boolean field in the end of `action_rfq_send'.
In report.py, select a query to fetch records where boolean_field =True and state ='purchase'.
Hope this will help you.
def onchange_stage_id(self, cr, uid, ids, stage_id, context=None):
if stage.name == 'Proposal':
print stage.name
return {
'type': 'ir.actions.act_window',
'res_model': 'sale.order',
'view_type': 'form',
'view_mode': 'form',
'target': 'new',
}
when i do this onchange i got an error
onchange_stage_values = self.onchange_stage_id(cr, uid, ids, vals.get('stage_id'), context=context)['value']
KeyError: 'value'`
It gives you a keyerror as the dictionary does not have any key by the name of 'value'.
The only keys present in the dictionary that you are returning are 'type', 'res_model', 'view_type', 'view_mode', and 'target'.
If you want to access the whole dictionary:
onchange_stage_values = self.onchange_stage_id(cr, uid, ids, vals.get('stage_id'), context=context)
This will put the whole dictionary in onchange_stage_values
I have created a custom header menu called 'HM-1'
And i have created a Menu called 'Menu 1'
Inside 'Menu 1' i have 3 fields created, called field_1 fileds_2 filed_3.
I created a 'User' and i have two users now
1. Admin
2. User
My question is 'How to make one field(field_3) 'User' and 'Admin' editable in Openerp-7'
Remaining fields in 'User' should be readonly only field_3 should be editable.
How to do this?
The first thing that come into my mind is to override fields_view_get and change the readonly and modifiers attribute of field_1 and field_2 based on groups of self.env.user. Of course you need to assign User to a specific group, different to the one of Admin.
class example_class(models.Model):
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
res = super(example_class, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu)
group = self.pool['ir.model.data'].xmlid_to_object(cr, uid, 'your_group', raise_if_not_found=True, context=context)
if view_type == 'form' and group in self.env.user.groups_id:
doc = etree.XML(res['arch'])
#this for cycle must be repeated for each field you need to make readonly
for node in doc.xpath("//field[#name='field_2']"):
if 'modifiers' in node.attrib:
text = node.attrib['modifiers']
j = json.loads(text)
j['readonly'] = '1'
else:
j = {'readonly': '1'}
node.attrib['modifiers'] = json.dumps(j)
res['arch'] = etree.tostring(doc)
return res
In Odoo/Openerp i created a kanban view to display some data. Now i managed to change this view with the fields_view_get based on context data.
def fields_view_get(self, cr, uid, view_id=None, view_type=False, context=None, toolbar=False, submenu=False):
if context is None:
context = {}
res = super(esfyt_subscription_template,self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu)
if context.get('partner_id', False):
partner_id = context.get('partner_id', False)
doc = etree.XML(res['arch'])
if view_type == 'kanban':
for node in doc.xpath("//div[#class='oe_module_vignette']"):
new_addition = etree.SubElement(node, 'button', {'string' : 'Subscribe', 'type' : 'object', 'name' : 'action_subscribe'})
new_addition.text = 'Subscribe'
res['arch'] = etree.tostring(doc)
return res
But i need to do the same with the data. i need to limit some data based on context, o certain models(or rows) arent loaded in the view.
How can i do that?
To filter records based on the context, you have to override the search() method
To filter data based on the context, you have to override the read()/browse() methods
What I need to do is access values of the columns in a certain module before it's saved.
For example, if we have a module defined like this:
_columns = {
'name': fields.char('Department Name', size=64, required=True),
'complete_name': fields.function(_dept_name_get_fnc, type="char", string='Name'),
'parent_id': fields.many2one('hr.department', 'Parent Department', select=True),
'child_ids': fields.one2many('hr.department', 'parent_id', 'Child Departments'),
'note': fields.text('Note'),
}
All those columns are represented by controls such as textbox, combobox, checkbox, etc.
When we open the form view in the create mode, a new record is being created but not saved and won't take an id in the database until we click (save).
The question is how to access the values of those fields (controls) before they are saved and before the current record takes a new id.
I know about self.browse and self.search but they need an ID which is not available because the record is not saved yet.
Also, can we assign a global variable that could be accessed from any class in the module (a session variable in web-development terms)?
Better override create method, and use the way you want. Try this in you object, Its an example,
def create(self, cr, uid, vals, context=None):
if vals.get('name','/')=='/':
vals['name'] = self.pool.get('ir.sequence').get(cr, uid, 'sale.order') or '/'
return super(sale_order, self).create(cr, uid, vals, context=context)
likewise you can do your changes from here itself, see the value of "vals" and "context",
this would be helpful to you.
If you want to access this field than you need to override the create method of orm. For Example:
def create(self, cr, uid, vals, context=None):
name = vals.get('name')
complete_name = vals.get('complete_name') # like all others field if one2many field comes than this field access using for loop.
vals.update({'your_field_name': your_value_what_you_want_to_update_before_creating})
#vals.update({'name': 'Your Good Name'})
return super(your_class_name, self).create(cr, uid, vals, context)
def write(self, cr, uid, ids, vals, context=None):
print "\n\n\nCurrent Values =>", vals
name = vals.get('name')
print "\nCurrent Name => ", name
complete_name = vals.get('complete_name') # like all others field if one2many field comes than this field access using for loop.
#do all calculation as you want and store in local variable and that variable pass as a value. for example.
name = 'Your Good Name'
vals.update({'name': name})
print "\n\nUpdated Values => ", vals
return super(your_class_name, self).write(cr, uid, ids, vals, context)
Hope this will help you.