Is there a solution to invoice delivered qty ? - odoo

I would like to know if there a solution to invoice just the delivered qty ( delivered qty - returned qty) in odoo
or I must code it ?

As I know there is no any option to invoice delivered qty.
You have to code for that option.

inherit _get_invoice_line_vals of stock_move in the module stock_account
def _get_invoice_line_vals(
...
#search for (deliverd - returnedQty)
qty = 0
quant_obj = self.pool.get("stock.quant")
uom_obj = self.pool.get('product.uom')
quant_search = quant_obj.search(cr, uid, [('history_ids', 'in', move.id), ('qty', '>', 0.0), ('location_id', 'child_of', move.location_dest_id.id)], context=context)
for quant in quant_obj.browse(cr, uid, quant_search, context=context):
if not quant.reservation_id or quant.reservation_id.origin_returned_move_id.id != move.id:
qty += quant.qty
qty = uom_obj._compute_qty(cr, uid, move.product_id.uom_id.id, qty, move.product_uom.id)
quantity = qty
# quantity = move.product_uom_qty
# set UoS if it's a sale and the picking doesn't have one
uos_id = move.product_uom.id
# if move.product_uos:
# uos_id = move.product_uos.id
# quantity = move.product_uos_qty
#
...

Related

where is product.list_price point to / declared?

#api.depends('list_price', 'price_extra')
#api.depends_context('uom')
def _compute_product_lst_price(self):
to_uom = None
if 'uom' in self._context:
to_uom = self.env['uom.uom'].browse(self._context['uom'])
for product in self:
if to_uom:
list_price = product.uom_id._compute_price(product.list_price, to_uom)
else:
list_price = product.list_price
product.lst_price = list_price + product.price_extra
on odoo product.product i dont see list_price field. but on code i find
product.list_price. where is product.list_price point to / declared ?

Grouping and summing quantity lines with same product

I have this function it filters in all selected MO's raw material lines, and then creates a report that is displayed in tree view.
But I have one problem, there can be allot lines with the same product. So my goal is to group all these lines and display them then just in one line with summed quantity.
Can someone help me with this?
class RawMaterialReport(models.Model):
_name = 'raw.material.report'
_description = 'Raw Material Report'
product_id = fields.Many2one('product.product', string='Product', required=False)
code = fields.Char(string='Code', required=True, readonly=True)
total_qty = fields.Float(string='Total Qty', digits=(6, 2), readonly=True)
virtual_qty = fields.Float(string='Forcasted Qty', digits=(6, 2), readonly=True)
origin = fields.Char(string='Origin', required=True, readonly=True)
production_id = fields.Many2one('mrp.production')
#api.multi
def open_raw_materials(self):
self.search([]).unlink()
mrp_productions = self._context.get('active_ids')
mrp_production = self.env['mrp.production'].browse(mrp_productions)
products_without_default_code = mrp_production.mapped('move_raw_ids').filtered(
lambda x: not x.product_id.default_code
)
raws = mrp_production.mapped('move_raw_ids').sorted(
key=lambda r: r.product_id.default_code
)
for r in raws:
vals = {
'product_id': r.product_id.id,
'code': r.product_id.default_code,
'total_qty': r.product_id.qty_available,
'virtual_qty': r.product_id.virtual_available,
'origin': r.reference,
'production_id': r.raw_material_production_id.id,
}
self.create(vals)
Instead of creating the record directly, keep them in dictionary grouped by product ID and when ever you find that the product all ready have a record just sum its
quantity.
#api.multi
def open_raw_materials(self):
self.search([]).unlink()
mrp_productions = self._context.get('active_ids')
mrp_production = self.env['mrp.production'].browse(mrp_productions)
products_without_default_code = mrp_production.mapped('move_raw_ids').filtered(
lambda x: not x.product_id.default_code
)
raws = mrp_production.mapped('move_raw_ids').sorted(
key=lambda r: r.product_id.default_code
)
# to group by product
recs = {}
for r in raws:
product_id = self.product_id.id
if product_id in recs:
# here just update the quantities or any other fields you want to sum
recs[product_id]['product_uom_qty'] += self.product_id.product_uom_qty
else:
# keep the record in recs
recs[product_id] = {
'product_id': r.product_id.id,
'code': r.product_id.default_code,
'total_qty': r.product_id.product_uom_qty,
'virtual_qty': r.product_id.virtual_available,
'origin': r.reference,
'production_id': r.raw_material_production_id.id,
}
for vals in recs.values():
# create records this will create a record by product
self.create(vals)

Filter lines by categ_id and count qty

My goal is to loop through all lines with the same categ_id and calculate total quantity they have and if qty_categ_total < categ_id.qty_for_discount ( I added this field to 'product.category' than I need to post a message in text fields. the problem my code is not working as I want.
Example.
If I have 2 lines with the same categ_id with qty 2 and 5 and my categ_id.qty_for_discount is 10. The message should say that I need to add 3 more products with the same categ_id to get discount
Update
And if there are products with different categories I should get a message for each category
class PurchaseOrder(models.Model):
_inherit = 'purchase.order'
discount_warning_message = fields.Text(string='Discount Warning', compute='discount_warning')
#api.depends('order_line.product_id', 'order_line.product_qty')
def discount_warning(self):
qty_categ_total = 0.0
for line in self.order_line:
qty_categ_total += line.product_qty
if qty_categ_total < line.product_id.categ_id.qty_for_discount:
message = (_("You can get discount if you add %s more %s\n")) % (qty_categ_total, line.product_id.categ_id.name)
self.discount_warning_message = message
Your code seems to be correct, but i would change something. First either use #api.one to let odoo automatically loop through all orders or add one more for each loop and #api.multi. And secondly what about more than one category?
#api.multi
#api.depends('order_line.product_id', 'order_line.product_qty')
def discount_warning(self):
msg = _("You can get discount if you add %s more %s\n")
for order in self:
categ_qtys = {}
for line in order.order_line:
if line.product_id.categ_id not in categ_qtys:
categ_qtys[line.product_id.categ_id] = 0.0
categ_qtys[line.product_id.categ_id] += line.product_qty
msgs = []
for categ, qty in categ_qtys.iteritems():
if qty < categ.qty_for_discount:
msgs.append(msg % (qty, categ.name))
if msgs:
order.discount_warning_message = "".join(msgs)
General advice: Always try to debug into your methods. Are they even called? If not, the methods aren't the problem.

how override creat method in sale order odoo 10 to add po RFQ

I am try to override create method in sale order to make purchase order with current data in sale order and my code did not work
Iam try this:
#api.multi
def creat(self):
# for order in self:
# order.state = 'sale'
# order.confirmation_date = fields.Datetime.now()
# if self.env.context.get('send_email'):
# self.force_quotation_send()
# order.order_line._action_procurement_create()
# if self.env['ir.values'].get_default('sale.config.settings', 'auto_done_setting'):
# self.action_done()
self.env['purchase.order'].create({'partner_id': partner_id.id,
'location_id':location_id.id,
'pricelist_id': pricelist_id.id,
'order_line': [(0, 0, {'product_id': product_id.id,
'name': name.id,
'date_planned': date_planned.id,
'price_unit': price_unit.id})]})
return True
You have to use api.model for create method as there is no id for the record when creating a new record.
here is a sample code
#api.model
def create(self, vals):
res = super(ClassName, self).create(vals)
# Your code here
# vals will contain dictionary of all variables.
return res
Also You don't have to change code for creating purchase order from sales.
You just have to set routes(Buy in this case) for the product and product's vendor.

TypeError: generate_purchase_order() takes exactly 1 argument (5 given)

I am trying to convert openerp 7 code to odoo8. In V7 browse() method had several parameters like self,cr,uid,ids,context but in V8 I think none of these is needed.In my custom module I am trying to create a purchase order based on the information obtained from mrp.I have done a custom calculation for how many Kgs of paper needed for 10000 quantities of books to be manufactured.After calculation this info should go to purchase invoice.Products will be obtained from bill of materials,quantity from no of kgs of paper needed and unit price from product cost attribute.I am unable to solve this error "method takes exactly 1 argument (5 given)"
mrp.py,
from openerp import models
class mrp_production(models.Model):
_inherit = 'mrp.production'
def generate_purchase_order(self,supplier_id,warehouse_id):
purchase_obj = self.env['purchase.order']
purchase_line_obj = self.env['purchase.order.line']
warehouse_obj = self.env['stock.warehouse']
warehouse = warehouse_obj.browse(warehouse_id)
if not warehouse:
return False
if isinstance(warehouse, list):
warehouse = warehouse[0]
for order in self:
vals = {}
vals = purchase_obj.onchange_partner_id()
vals['origin'] = order.name
vals['partner_id'] = supplier_id
vals['warehouse_id'] = warehouse_id
vals['location_id'] = warehouse.lot_stock_id.id
vals['date_order'] = order.date_planned
purchase_id = purchase_obj.create(vals)
for line in self.bom_id.bom_line_ids:
if not line.product_id:
continue
line_vals = purchase_line_obj.onchange_product_id(line.product_id.id,
line.product_uom_qty, line.product_uom.id, supplier_id,
date_planned=line.date_planned)['value']
line_vals['name'] = line.name
line_vals['product_id'] = line.product_id.id
if not line_vals.get('price_unit', False):
line_vals['price_unit'] = line.product_id.list_price
line_vals['product_uom'] = line.product_uom.id
line_vals['product_uom_qty'] = 181.13
line_vals['order_id'] = purchase_id
purchase_line_obj.create(line_vals)
return True
generate_purchase_order.py,
from openerp import models,fields,api
class generate_purchase_order(models.Model):
_name = 'mrp_to_purchase_order.generate_purchase_order'
_description = 'Generate Purchase Order'
partner_id = fields.Many2one('res.partner', 'Supplier', required=True, domain="[('supplier','=',True)]")
warehouse_id = fields.Many2one('stock.warehouse', 'Warehouse', required=True)
#api.multi
def onchange_partner_id(self,partner_id):
return {}
def generate_purchase_order(self):
for wizard in self:
#mrp_order_ids = [context['active_id']]
mrp_obj = self.env['mrp.production']
mrp_obj.generate_purchase_order(wizard.partner_id.id, wizard.warehouse_id.id)
return { 'type': 'ir.actions.act_window_close'}
If you are calling the generate_purchase_order method from some other method in your model, then use the decorator #api.multi for that method.
Also in your generate_purchase_order method, replace
for order in self.browse():
by
for order in self:
EDIT
#api.multi
def generate_purchase_order(self):
for wizard in self:
#mrp_order_ids = [context['active_id']]
mrp_obj = self.env['mrp.production']
# Get the mrp record
mrp_rec = code to get mrp record
mrp_rec.generate_purchase_order(wizard.partner_id.id, wizard.warehouse_id.id)
return { 'type': 'ir.actions.act_window_close'}