Update stock move record which is done odoo - odoo

I am working in odoo 8, i have to update the stock move which is done. i.e. suppose the move was done and state becomes "done" but the quantity entered was incorrect, so to correct it i need to reduce the quantity of that move.
I am trying to update the quantity but it gives me error as :
_('Quantities, Units of Measure, Products and Locations cannot be modified on stock moves that have already been processed (except by the Administrator).'))
I was trying as below:
move.write({'product_uos_qty':correct_qty})
I also tried this:
move.sudo().write({'product_uos_qty':correct_qty})
Always i get the same error.
Please Help
Thanks,

The easiest way without getting into security or removing the constrains or restrictions Odoo put in place is to use sql. Just write the raw sql that accomplishes your task and execute it where you were trying to do your write above. Not sure if it is the best way. But in your addon you can inherit stock.move and completely override the function. Or just edit the file manually and restart your server. Not sure about the other problems it might cause but it should let your write to the field.
sql = ".....YOUR SQL HERE"
self.env.cr.execute(sql)
self.env.cr.commit()
Override the write function in addons/stock/stock.py
def write(self, cr, uid, ids, vals, context=None):
if context is None:
context = {}
if isinstance(ids, (int, long)):
ids = [ids]
# Check that we do not modify a stock.move which is done
frozen_fields = set(['product_qty', 'product_uom', 'product_uos_qty', 'product_uos', 'location_id', 'location_dest_id', 'product_id'])
for move in self.browse(cr, uid, ids, context=context):
if move.state == 'done':
#if frozen_fields.intersection(vals):
# raise osv.except_osv(_('Operation Forbidden!'),
# _('Quantities, Units of Measure, Products and Locations cannot be modified on stock moves that have already been processed (except by the Administrator).'))
propagated_changes_dict = {}
#propagation of quantity change
if vals.get('product_uom_qty'):
propagated_changes_dict['product_uom_qty'] = vals['product_uom_qty']
if vals.get('product_uom_id'):
propagated_changes_dict['product_uom_id'] = vals['product_uom_id']
#propagation of expected date:
propagated_date_field = False
if vals.get('date_expected'):
#propagate any manual change of the expected date
propagated_date_field = 'date_expected'
elif (vals.get('state', '') == 'done' and vals.get('date')):
#propagate also any delta observed when setting the move as done
propagated_date_field = 'date'
if not context.get('do_not_propagate', False) and (propagated_date_field or propagated_changes_dict):
#any propagation is (maybe) needed
for move in self.browse(cr, uid, ids, context=context):
if move.move_dest_id and move.propagate:
if 'date_expected' in propagated_changes_dict:
propagated_changes_dict.pop('date_expected')
if propagated_date_field:
current_date = datetime.strptime(move.date_expected, DEFAULT_SERVER_DATETIME_FORMAT)
new_date = datetime.strptime(vals.get(propagated_date_field), DEFAULT_SERVER_DATETIME_FORMAT)
delta = new_date - current_date
if abs(delta.days) >= move.company_id.propagation_minimum_delta:
old_move_date = datetime.strptime(move.move_dest_id.date_expected, DEFAULT_SERVER_DATETIME_FORMAT)
new_move_date = (old_move_date + relativedelta.relativedelta(days=delta.days or 0)).strftime(DEFAULT_SERVER_DATETIME_FORMAT)
propagated_changes_dict['date_expected'] = new_move_date
#For pushed moves as well as for pulled moves, propagate by recursive call of write().
#Note that, for pulled moves we intentionally don't propagate on the procurement.
if propagated_changes_dict:
self.write(cr, uid, [move.move_dest_id.id], propagated_changes_dict, context=context)
return super(stock_move, self).write(cr, uid, ids, vals, context=context)

Related

Qty on hand filter missmatch

I have this 2 product that shown in the first picture, and they have "Qty on hand" is zero
after that, I go to advanced filter and filter by "Qty on hand' = 0.0, and now this 2 product disappear.
this method is responsible for the search and i can't figure out why is he working not correctly.
def _search_product_quantity(self, cr, uid, obj, name, domain, context):
prod = self.pool.get("product.product")
product_variant_ids = prod.search(cr, uid, domain, context=context)
return [('product_variant_ids', 'in', product_variant_ids)]
this method is from the original Odoo module you can find it in stock/product.py line 376.
[enter image description here][1]
[1]: https://i.stack.imgur.com/f2jMR.jpg already work i am checked with odoo9.0

Set sales order fields reference in picking - odoo

I would like to set Sales Team reference in picking directly when sales order confirm and picking is getting created.
But I didn't get enough hint how can I achieve this. Because the method which is called at the time of sales order confirmation is as follow.
def action_button_confirm(self, cr, uid, ids, context=None):
if not context:
context = {}
assert len(ids) == 1, 'This option should only be used for a single id at a time.'
self.signal_workflow(cr, uid, ids, 'order_confirm')
if context.get('send_email'):
self.force_quotation_send(cr, uid, ids, context=context)
return True
Here there is no any hint how can I pass it to picking ?
Purpose:
My aim is to set sales team reference in picking / shipment.
It's not that easy. Odoo uses procurement.orders for creating stock.moves and for them stock.pickings. Problem: Maybe a picking has more than one sales orders as origin. So there could be more than one sales team referenced.
But try to use a computed field:
section_id = fields.Many2one(
comodel_name="crm.case.section", string="Sales Team",
compute="_compute_section_id")
#api.multi
def _compute_section_id(self):
for picking in self:
section_ids = set()
for move in picking.move_lines:
if move.sale_line_id.order_id.section_id
section_ids.add(move.sale_line_id.order_id.section_id.id)
if len(section_ids) == 1:
picking.section_id = section_ids.pop()
You could also use a related field, but that could have really bad side effects. Because Odoo will take the first move.
section_id = fields.Many2one(
comodel_name="crm.case.section", string="Sales Team",
related="move_lines.sale_line_id.order_id.section_id")
I got that method from where it create picking. So I have just inherited it and added my code. action_ship_create will always get called at the time of shipment creation from the sales order.
#api.cr_uid_ids_context
def action_ship_create(self,cr,uid,ids,context={}):
result=super(sale_order,self).action_ship_create(cr,uid,ids,context=context)
for order in self.browse(cr,uid,ids,context=context):
order.picking_ids.write({'section_id':order.section_id.id})
return result

Assign value from one class to another

So in class 1 for example I calculate a price and I want to assign this price to a field from class 2 for example.
How can I achieve this, I tried the following without success:
self.browse(cr, uid, ids[0]).task_id.xx_new_price = new_price
xx_new_price is a field from another class which I can access trough task_id. new_price just contains a number.
EDIT: Updated with code
class PurchaseOrder(osv.Model):
_inherit = 'purchase.order'
def wkf_confirm_order(self, cr, uid, ids, context=None):
new_price = self.pool.get('price.calculation').calculate_price(cr, uid, ids, context=context)
for purchase_order in self.browse(cr, uid, ids):
if purchase_order.task_id:
task = self.pool.get('project.task').browse(cr, uid, purchase_order.task_id)[0]
task.write({'xx_new_price': new_price})
_columns = {
'project_id': fields.many2one('project.project', 'Project'),
'task_id': fields.many2one('project.task', 'Task')
}
So I inherit the wkf_confirm method from purchase order (I left all the standard code out for this example). Because when I confirm an order I want it to assign a value to another field from another class (in this case the to the field xx_new_price in project.task. new_price calculates a price and contains a float.
For write a new value in table, you need to call write of ORM for that class.
First you should take a task_id from the current object and than assign a new_price
For example:
for project in self.browse(cr, uid, ids):
if project.task_id:
project.task_id.write({'xx_new_price': new_price})

Show error message when record is duplicate in my sale order line of openerp

What should i do to show error message in openerp when there is a duplicate line in sale order line record?
I can't get any way to test it in my project.
You can use _sql_constraints
This e.g is from account_payment:
_sql_constraints = [
('name_uniq', 'UNIQUE(name)', 'The payment line name must be unique!'),
]
Hope this will help you.
Regards,
You should create a module that extends the sale.order.line model and adds the constraint that checks for the duplicate. You can find further information here:
https://doc.openerp.com/v6.1/developer/03_modules_2/
You can display the warning message using osv package,
if True:
raise osv.except_osv(_('Warning!'),_('You cannot delete a leave'))
def action_confirm(self, cr, uid, ids, context=None):
move_obj = self.pool.get('stock.move')
for procurement in self.browse(cr, uid, ids, context=context):
cr.execute("select id,order_id,foc from sale_order_line where product_id = %s and order_id= %s and foc = %s", (procurement.product_id.id, procurement.move_id.sale_line_id.order_id.id, procurement.foc,))
data = cr.fetchall()
count = len(data)
if count >= 2:
raise osv.except_osv(_('Data Duplicate!'),
_('Please check the sale order line.Duplicate

Create sequence for opportunity

I am using Openerp 6.1.1.
I want to create a sequence for only leads that become opportunity but not for all leads.
Since both leads and opportunity are modelled using the same table, it's not clear how to achieve this. Please suggest.
Thanks in advance.
You can add a sequence field in object. And when click on Button "Convert to Opportunity"
you can assign the sequence to this lead.
OR when you want to create opportunity from Opportunity menu then you overwrite the create method and in create method check type of record if type 'opportunity' then assign the sequence in record.
Thanks
i got this working finally.
Overriding convert_opportunity() was not possible since it may contain a list of ids which I couldn't figure out how to pass the sequence to. So I had to overwrite the _convert_opportunity_data() method (not a good choice though !).
def create(self, cr, uid, vals, context={}):
if vals['type']=='opportunity':
next_seq = self.pool.get('ir.sequence').get(cr, uid, 'crm.lead')
vals['seq'] = next_seq
res = super(crm_sequence, self).create(cr, uid, vals, context)
return res
def _convert_opportunity_data(self, cr, uid, lead, customer, section_id=False, context=None):
vals = super(crm_sequence, self)._convert_opportunity_data(cr, uid, lead, customer, section_id, context)
next_eq = self.pool.get('ir.sequence').get(cr, uid, 'crm.lead')
vals['seq'] = next_seq
return vals