Set sales order fields reference in picking - odoo - 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

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

Method to get product price for a given customer

I need to retrieve product price via XMLRPC.
I am using Product Price Lists so each customer can be assigned a given price list which gives specific discounts based on categories, etc.
I am struggling to find which method can be used to retrieve the price for a given product_template id at a given quantity, if that is actually possible.
So far I have not been able to try any specific method as I can not identify how can this be achieved without actually creating a sales order.
The module 'product' holds the pricelist mechanics. The model product.pricelist has a really nice method get_product_price(), which could be easily used server-side but not for the external/web API.
But if you have the possibility to write a little custom module, do that and override the model product.pricelist. Add the possibility to use this method, like:
Origin Method which can't be used because parameters are RecordSets:
def get_product_price(self, product, quantity, partner, date=False, uom_id=False):
""" For a given pricelist, return price for a given product """
self.ensure_one()
return self._compute_price_rule([(product, quantity, partner)], date=date, uom_id=uom_id)[product.id][0]
"Wrapper" for external/web API:
def web_api_get_product_price(
self, product_id, quantity, partner_id, date=False, uom_id=False):
""" For a given pricelist, return price for a given product
callable from web api"""
self.ensure_one()
# get records
product = self.env['product.product'].browse(product_id)
partner = self.env['res.partner'].browse(partner_id)
# call origin method
return self.get_product_price(
product, quantity, partner, date=date, uom_id=uom_id)
Now you can call this method, an example:
import xmlrpclib
db = 'db_name'
password = 'admin'
common = xmlrpclib.ServerProxy('http://localhost:8069/xmlrpc/2/common')
uid = common.authenticate(db, 'admin', password, {})
models = xmlrpclib.ServerProxy('http://localhost:8069/xmlrpc/2/object')
pricelist_id = 1
product_id = 5
partner_id = 7
quantity = 20
price = models.execute_kw(
db, uid, password, 'product.pricelist',
'web_api_get_product_price',
[[pricelist_id], product_id, quantity, partner_id], {})

Update stock move record which is done 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)

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})

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