How to merge Lot/Serial number - view

I want to add a wizard with Many2many field of 'stock.production.lot' displaying only the records with doubled Lot/Serial Number
i did the function that get the filtred records ,now i need to display it
class DoublingNumber(models.TransientModel):
_name = 'doubling.number'
double_number_id =fields.Many2many('stock.production.lot' ,string="Numéros en doublant" )
#api.multi
def _default_double_number(self):
log.warning("Hola")
double_record = []
records =self.env['stock.production.lot'].search([])
for record in records :
for record2 in records :
if record.name == record2.name and record.product_id != record2.product_id :
double_record.append(record2)
break
return double_record
Now how to display it ??!

Try calling the default function within the field definition, but define the function before the field and define it in the following way instead :
class DoublingNumber(models.TransientModel):
_name = 'doubling.number'
#api.model
def _default_double_number(self):
log.warning("Hola")
double_record = self.env['stock.production.lot']
records =self.env['stock.production.lot'].search([])
for record in records :
for record2 in records :
if record.name == record2.name and record.product_id != record2.product_id :
double_record += record2
break
return double_record
double_number_id =fields.Many2many('stock.production.lot' ,string="Numéros en doublant", default = _default_double_number)
Good luck :)

Related

one2many field get row number

I have a module contain one2many filed.
while I create data line in this o2m field, I'd like to append a row number to it.
I have try some method that I found in forum, like this link.
but since I have no function called _onchange_partner_id() , I don't know how to use it.
or this link .
but it seems like an old version method that I can't get well.
class YcWeight(models.Model):
_name = "yc.weight"
customer_detail_ids = fields.One2many("yc.weight.details", "name", "customer details")
class YcWeightDetails(models.Model):
_name = "yc.weight.details"
name = fields.Many2one("yc.weight", "weight detail list", ondelete="cascade")
no = fields.Integer("row number")
the "no" is a field that I want to show number of row count.
my problem is :
how can I get get the number of rows?
since onchage decorated function can't get data from db.
I find a solution by myself and it is simple:
use depends decorator.
class YcWeightDetails(models.Model):
_name = "yc.weight.details"
name = fields.Many2one("yc.weight", "weight detail list", ondelete="cascade")
no = fields.Integer("row number")
compuute_no = fields.Integer("invisible field", compute= "_get_row_no")
create a field "compuute_no" to compute.
#api.depends("compuute_no")
def _get_row_no(self):
if self.ids:
count =1
for rec in self:
weight_id = self.env['yc.weight.details'].search([('id','=', rec.id)])
weight_id.write({'no': count})
count+=1
or overwrite create method
#api.model
def create(self, vals):
main_key = self.env["yc.weight"].search([], order="id desc", limit=1).id
item_key = vals["name"]
if item_key and main_key == item_key:
number = len(self.env["yc.weight.details"].search([("name", "=", item_key)]))
vals.update({"no": number + 1})
return super(YcWeightDetails, self).create(vals)
hope it can help you.

Rewrite an OpenERP 7 method to Odoo 8 syntax?

I have the following OpenERP 7 method:
# Function to get the vat number (CIF/NIF) and then show it on invoice form view
def _get_vat_num(self, cr, uid, ids, field_name, args=None, context=None):
partner_pool = self.pool.get('res.partner')
invoice_pool = self.pool.get('account.invoice')
res = {}
for inv in self.browse(cr, uid, ids, context=context):
invoice = invoice_pool.browse(cr,uid, inv.id, context=None)
partner = partner_pool.browse(cr, uid, invoice.partner_id.id, context=None)
res[inv.id] = partner.vat
return res
inv_vat = fields.Char(compute='_get_vat_num', string="CIF/NIF")
I need to rewrite it to Odoo v8 syntax. I have tried but it doesn't work:
def _get_vat_num(self):
partner_pool = self.env['res.partner']
invoice_pool = self.env['account.invoice']
res = {}
for inv in self.browse(self.id):
invoice = invoice_pool.browse(inv.id)
partner = partner_pool.browse(invoice.partner_id.id)
res[inv.id] = partner.vat
return res
What should be the correct code?
It looks like you're setting a functional field. You should instead be able to define the field as a related field like so:
inv_vat = fields.Char(string="VAT", related="partner_id.vat")
If you really want it as a functional field, this is how you would do it
inv_vat = fields.Char(string="VAT", compute="_get_vat_num")
def _get_vat_num(self):
# self is a recordset of account.invoice records
for invoice in self:
# to set a functional field, you just assign it
invoice.inv_vat = invoice.partner_id.vat
Check out the recordset documentation: https://www.odoo.com/documentation/8.0/reference/orm.html#recordsets
And the computed fields documentation:
https://www.odoo.com/documentation/8.0/reference/orm.html#computed-fields

How can I create a complete_name field in a custom module for a custom hierarchy like used on product categories in Odoo?

I'm trying to create a field “complete_name” that displays a hierarchy name similar to whats done on the product categories grid but I can't seem to get it to work. It just puts Odoo in an endless loading screen when I access the relevant view using the new field "complete_name".
I have tried to copy the code used in addons/product/product.py and migrate to work with Odoo 9 API by using compute instead of .function type but it did not work.
Can someone help me understand whats wrong? Below is my model class which works fine without the complete_name field in my view.
class cb_public_catalog_category( models.Model ):
_name = "cb.public.catalog.category"
_parent_store = True
parent_left = newFields.Integer( index = True )
parent_right = newFields.Integer( index = True )
name = newFields.Char( string = 'Category Name' )
child_id = newFields.One2many( 'catalog.category', 'parent_id', string = 'Child Categories' )
complete_name = newFields.Char( compute = '_name_get_fnc', string = 'Name' )
def _name_get_fnc( self ):
res = self.name_get( self )
return dict( res )
Your compute function is supposed to define the value of an attribute of your class, not return a value. Ensure the value you are assigning complete_name is a string.
Also name_get() returns a tuple. I am not sure if you really want a string representation of this tuple or just the actual name value.
Try this
def _name_get_fnc( self ):
self.complete_name = self.name_get()[1]
If you really want what is returned by name_get() then try this.
def _name_get_fnc( self ):
self.complete_name = str(self.name_get())
If you are still having issues I would incorporate some logging to get a better idea of what you are setting the value of complete_name to.
import logging
_logger = logging.getLogger(__name__)
def _name_get_fnc( self ):
_logger.info("COMPUTING COMPLETE NAME")
_logger.info("COMPLETE NAME: " + str(self.name_get()))
self.complete_name = self.name_get()
If this does not make it apparent what the issue is you could always try statically assigning it a value in the off chance that there is a problem with your view.
def _name_get_fnc( self ):
self.complete_name = "TEST COMPLETE NAME"
After further review I think I have the answer to my own question. It turns out as with a lot of things its very simple.
Simply use "_inherit" and inherit the product.category
model. This gives access to all the functions and fields
of product.category including the complete_name field
and computes the name from my custom model data. I was
able to remove my _name_get_func and just use the inherited
function.
The final model definition is below. Once this
update was complete I was able to add a "complete_name" field
to my view and the results were as desired!
class cb_public_catalog_category( models.Model ):
_name = "cb.public.catalog.category"
_inherit = 'product.category'
_parent_store = True
parent_left = newFields.Integer( index = True )
parent_right = newFields.Integer( index = True )
name = newFields.Char( string = 'Category Name' )
child_id = newFields.One2many( 'catalog.category', 'parent_id', string = 'Child Categories' )

How to add a filter to selection field in odoo

I need to add a filter to a selection field in odoo..
roomuser = fields.Selection([('stpi', 'Belongs to Park'),('Incubation', 'Belongs to Incubation companies'),('both', 'Belongs to Park& Incubation companies')],'Room Assignment',required=True)
roomType = fields.Selection([('meeting','Meeting Room'),('discussion','Discussion Room'),('auditorium','Auditorium'),('board','Board Room')],required=True)
Here i need to filter the value of roomType based on the value of roomuser. Suppose roomuser value is both only auditorium and board should be visible in roomType
I have made my comments as below , kindly request you to find it as below it may help in your case:
class HotelManagement(models.Model):
_name='hotel.management'
#api.model
def _get_room_type_list(self):
# [('meeting','Meeting Room'),('discussion','Discussion Room'),('auditorium','Auditorium'),('board','Board Room')]
vals=[]
for record in self.env['hotel.management'].search([]):
if record.roomuser in ['stpi','Incubation'] :
vals.extend([('meeting','Meeting Room'),('discussion','Discussion Room')])
if record.roomuser in ['both'] :
vals.extend([('auditorium','Auditorium'),('board','Board Room')])
return vals
def _get_roomuser_list(self):
return [('stpi', 'Belongs to Park'),
('Incubation', 'Belongs to Incubation companies'),
('both', 'Belongs to Park& Incubation companies')]
roomType=fields.Selection(string="Room Type", selection=_get_room_type_list, default='meeting', required=True)
roomuser = fields.Selection(string="Room Assignment",selection=_get_roomuser_list ,required=True)
Here i have just put #api.model on top _get_room_type_list and traversing all the record in this(hotel.management) model and filtering the selection field .

LINQ to Entities does not recognize the method 'Int32 Min(Int32, Int32)'?

Im getting this error when I execute the following code, any Ideas how to fix it?
LINQ to Entities does not recognize the method 'Int32 Min(Int32, Int32)' method, and this method cannot be translated into a store expression.
result = items.ToList()
.Select(b => new BatchToWorkOnModel()
{
BatchID = b.Batch.ID,
SummaryNotes = b.Batch.Notes,
RowVersion = b.Batch.RowVersion,
Items = items
.Select(i => new ItemToWorkOnModel()
{
SupplierTitle = i.Title,
ItemID = i.ID,
BatchID = i.BatchID ?? 0,
ItemDate = i.PubDate,
// KB - Issue 276 - Return the correct Outlet name for each item
Outlet = i.Items_SupplierFields != null ? i.Items_SupplierFields.SupplierMediaChannel != null ? i.Items_SupplierFields.SupplierMediaChannel.Name : null : null,
Status = ((short)ItemStatus.Complete == i.StatusID ? "Done" : "Not done"),
NumberInBatch = i.NumInBatch,
Text = string.IsNullOrEmpty(i.Body) ? "" : i.Body.Substring(0, Math.Min(i.Body.Length, 50)) + (i.Body.Length < 50 ? "" : "..."),
IsRelevant = i.IsRelevant == 1,
PreviouslyCompleted = i.PreviouslyCompleted > 0 ? true : false
}).ToList()
})
.FirstOrDefault();
It seems Math.Min is not implemented by the EF query provider. You should be able to fix it by simply applying AsEnumerable on your items collection to do the expression using Linq to Objects instead;
Items = items.AsEnumerable().Select(i => new ItemToWorkOnModel()...
If you add a where condition to the item selection (seems a little strange to take all items in the whole table), you'll want to add it before AsEnumerable() to allow EF to do the filtering in the database.
Also, you only want the first result from the query, but you're fetching all of them using ToList() before cutting the list down to a single item. You may want to remove the ToList() so that EF/the underlying database can return only a single result;
result = items.Select(b => new BatchToWorkOnModel()...
You do not need Math.Min.
The line in question is:
Text = string.IsNullOrEmpty(i.Body)
? "" : i.Body.Substring(0, Math.Min(i.Body.Length, 50)) + (i.Body.Length < 50 ? "" : "...")
So what does this line return?
If i.Body is null or empty it returns an empty string. If it is 50 or more characters long it returns a substring of 50 characters and appends "...".
If the length is less than 50 it takes a substring with the length of the string and appends an empty string. But that's just the original string.
Text = string.IsNullOrEmpty(i.Body)
? "" : (i.Body.Length < 50 ? i.Body : i.Body.Substring(0, 50) + "...")

Resources