I wonder if there is some way to show in one field, a concatenation of 3 other fields, already in the same form.
Like for example:
'field_1' : fields.integer('Campo 1'),
field_2' : fields.integer('Campo 2'),
field_3' : fields.integer('Campo 3'),
Then show the inputs of these 3 fields concatenated in one single field:
field_concatenated : fields.related(?)('field_1', 'field_2', 'field_3', 'Name of the field'),
I put an '?' sign cause i actually don't know how to achieve this, maybe using a related type one? By the way the 3 fields are on the same class-form.
The resulting field could be readonly, and show up after the form has been saved.
I hope i've explained myself.
Thanks in advance
EDIT
The fields can be of the type integer and char
2nd EDIT
Actual Example:
'empresa' : fields.integer('Empresa'),
'provee' : fields.integer('Proveedor'),
'soli_cant' : fields.integer('Cantidad de Solicitudes'),
'dest' : fields.char('Destino'),
'anho' : fields.integer('Año'),
So, after these fields are filled manually, the resulting field have to show me a concatenation of these 4 fields, in a format like empresa-proveesoli_cant-dest-anho
Being provee and soli_cant one after the another, (without the '-') if it can't be possible then that show me the concatenation without separator
Maybe it isn't necessarily declared on the python code, maybe there is some shortcut in the xml view?
Something like <field name="empresa" "provee" "soli_cant" "dest" "anho" /> idk...
3rd EDIT
The actual code i'm using right now (Thanks to Ethan Furman):
The columns:
'empresa' : fields.integer('Empresa'),
'provee' : fields.integer('Proveedor'),
'soli_cant' : fields.integer('Cantidad de Solicitudes'),
'dest' : fields.char('Destino'),
'anho' : fields.integer('Año'),
The function with it's column:
def _combinalos(self, cr, uid, ids, field_name, args, context=None):
values = {}
for id in ids:
rec = self.browse(cr, uid, [id], context=context)[0]
values[id] = {}
values[id][field_name] = '%s %s %s %s %s' %(rec.empresa, rec.provee, rec.soli_cant, rec.dest, rec.anho)
return values
columns = {
'nombre' : fields.function(_combinalos, string='Referencia de Pedido', type='char', arg=('empresa','provee','soli_cant', 'dest', 'anho'), method=True),
All this on the same class of course.
Then i call it from my xml view like this:
<h1>
<label string="Request for Quotation " attrs="{'invisible': [('state','not in',('draft','sent'))]}"/>
<label string="Purchase Order " attrs="{'invisible': [('state','in',('draft','sent'))]}"/>
<field name="nombre" class="oe_inline" readonly="1" />
</h1>
The label string is to filter if this is a Request for Quotation or a Purchase Order
After all this, i do fill the 5 fields of integer and char type, but still don't get these fields 'concatenated' in one string, or title, just a label saying [object Object], it could be a label issue? String name of function in the column maybe?
Make a new functional field and combine the three other fields there:
def _combine(self, cr, uid, ids, field_name, args, context=None):
values = {}
for id in ids:
rec = self.browse(cr, uid, [id], context=context)[0]
values[id] = {}
values[id] = '%s %s %s' % (rec.field1, rec.field2, rec.field3)
return values
_columns = {
...
fields.function(_combine, string='three fields in one!', type='char',
arg=('field1','field2','field3'), method=True),
Note: untested code
The _combine method should be part of the class with the other columns, and the fields.function should also be in that class' _columns.
Related
Below code is asset inherited class . Here i will add 'place' field with 'Karn/Bang/Kengeri' and 'karn/bang/malleshwaram' for 'Karn/Bang/Kengeri' will add 'asset_catg_id' with A and B. then for 'karn/bang/malleshwaram' with Y and Z.
Now at calander inherited class . if i select 'place' with 'Karn/Bang/Kengeri' then next field 'asset_catg_id' i have to get only A and B drop down list. if again 'karn/bang/malleshwaram' then i have to get only Y,Z options . and previous selected 'asset_catg_id' values should get deleted . i have tried with domain filter option got keyvalue error
class asset_asset(osv.osv):
_inherit = "asset.asset"
#_name = "asset_asset"
_rec_name= "folio_num"
_columns = {
'name': fields.char('Asset Name', size=64),
'place': fields.many2one('asset.parentlocation', 'Location'),
'asset_catg_id' : fields.many2one('asset.catg', 'Asset Catg Selection', select=True, required=True),}
class asset_catg(osv.Model):
_name="asset.catg"
_rec_name='name1'
_description="Define Asset Catgs"
_columns={ 'name1':fields.char('Asset Catg Names',size=64,required=True),}
asset_catg()
class asset_parentlocation(osv.osv):
_name="asset.parentlocation"
_rec_name="location_name"
_columns = {
'location_name' : fields.char('Asset Location', required=True),
'parent_location' : fields.many2one('asset.parentlocation','Parent Location'),
'nameee':fields.many2one('ir.attachment','Attachments'),}
def name_get(self, cr, uid, ids, context=None):
if context is None:
context = {}
if not ids:
return []
reads = self.read(cr, uid, ids, ['location_name','parent_location'], context=context)
res = []
for record in reads:
name = record['location_name']
if record['parent_location']:
name = record['parent_location'][1]+' / '+name
res.append((record['id'], name))
return res
**Following code is calendar inherited class**
class calendar_event(osv.osv):
_inherit = "calendar.event"
_rec_name = 'number'
_columns = {
'number' : fields.char('Meeting ID',readonly=1),
#'place' : fields.many2one('stock.location','Substation Location',),
'place' : fields.many2one('asset.parentlocation','Substation Location',),
#'location' : fields.selection(STATUS_SELECTION,'Location', default='Board A'),
'asset_catg_id' : fields.many2one('asset.catg','Asset Catg Selection', domain="[('asset_catg_id', '=',place)]"),}
First your domain is wrong in a principle. Domain is what is "inside" a field, in other words in its model (for example field name or id in asset.catg model). So you should fix that one first.
If domain depends on another field, you can use onchange method to return domain (used placeholder place_id). Like this:
#api.onchange('place')
def onchange_place(self):
res = {}
if self.place:
res['domain'] = {'asset_catg_id': [('place_id', '=', self.place.id)]}
return res
P.S. This is example with new v8 api, but same principle applies to old api (you then don't nee to use decorator, also add cr, uid, ids on method and call it through your view. All of this not needed for new api). As it looks like you are still developing on old api.
Update
For old api:
def onchange_place(self,cr, uid, ids, place, context=None):
res = {}
if self.place: #on old api it will return id, instead of record
res['domain'] = {'asset_catg_id': [('place_id', '=', self.place)]}
return res
And then in your view (don't know what kind of view you are using):
<field name="place" on_change="onchange_place(place)"/>
Still you need to define some field in asset.catg so it would be used to match place field. For example:
'place_id': fields.many2one('asset.parentlocation', 'Place')
And then when you define asset category, you set which Place it should belong to. Then when you choose place calendar.event, onchange method will set domain on asset_catg_id field correctly.
So far I'm trying to get a date field data, translated into text format in OpenERP v7.
I made a function on stock module, but when I declare this on my xml view, it returns Undefined tag, and I can't group line by date anymore.
This is my code:
def _date_(self, cr, uid, ids, fields, arg, context):
x={}
for record in self.browse(cr, uid, ids):
if record.create_date :
a = date.strptime(record.create_date, "%Y-%m-%d")
b = a.strftime("%Y-%m-%d")
x[record.id] = text(b(a))
return x
_columns = {
'create_date': fields.date('Creation Date', readonly=True, select=True),
'date_': fields.function(_date_, type='text', string='date copy', store=True),
And on stock_view.xml
<filter string="Creation" name="groupby_create_date" icon="terp-go-month" domain="[]" context="{'group_by':'date_'}"
It doesn't actually group them, but show 'undefined' tag, and groups all lines without discrimination by month, which is the normal behavior of create_date date type field, so, how can I achieve this?
I'm making some tests, but I don't see any change on it.
Can someone please shed some light on this?
Thanks in advance!
'date_': fields.function(date, type='date', string='date copy', store=True)
x[record.id] = text(b(a))
and not convert date in text type
Hope this help
I'm trying to show a res.partner field, which is called phone into the treeview of a sale.order.
But it is not showing anything, just the name of the field without data. This is my code on sale.order
phone : fields.char('Telefono del Cliente'),
Onchange function for this field:
def onchange_phone(self, cr, uid, ids, phone, context=None):
res = {}
if phone:
obj = self.pool.get('res.partner')
browse(cr, uid, phone)
res['phone'] = obj.phone
return {'value' : res}
On res.partner the field is also called phone which is obviously the client's phone, i need to show it on the sale.order treeview, this is the code on my sale_view.xml:
<field name="phone" on_change="onchange_phone(phone)"/>
Any ideas?
Thanks in advance.
As a suggestion, If you want phone number of partner, than you should not create on_change of phone field. You can get phone number in 2 ways.
First way and best way, In sale.order, onchange_partner_id() method is their, you need to override that method and update vals with phone number of partner.
And Second way and long way, You may override create() method and write() method of sale.order.
create() method trick:
in create() method, you can take partner id from the context. For example vals.get('partner_id')
write() method trick:
in write() method, you have id of created record so you need to simply browse that record and write phone number of partner.
As Odedra suggested, you should do this like so (this is taken from sale.py file):
def onchange_partner_id(self, cr, uid, ids, part, context=None):
if not part:
return {'value': {'partner_invoice_id': False, 'partner_shipping_id': False, 'payment_term': False, 'fiscal_position': False}}
part = self.pool.get('res.partner').browse(cr, uid, part, context=context)
addr = self.pool.get('res.partner').address_get(cr, uid, [part.id], ['delivery', 'invoice', 'contact'])
pricelist = part.property_product_pricelist and part.property_product_pricelist.id or False
payment_term = part.property_payment_term and part.property_payment_term.id or False
fiscal_position = part.property_account_position and part.property_account_position.id or False
dedicated_salesman = part.user_id and part.user_id.id or uid
phone = part.phone or False
val = {
'partner_invoice_id': addr['invoice'],
'partner_shipping_id': addr['delivery'],
'payment_term': payment_term,
'fiscal_position': fiscal_position,
'user_id': dedicated_salesman,
'phone': phone,
}
if pricelist:
val['pricelist_id'] = pricelist
return {'value': val}
Note that you should not do that on base module, but instead create your own module and inherit it to sale.order model. What is more, onchange will not work on tree view (like you suggested), but you can easily show it on the tree - you have to first put it on your form with the onchange provided, then modify tree view to show phone number.
I am new to OpenERP (v7) and am writing a module that extends the res.partner class and added the following two fields :
_columns = {
'member_ids': fields.one2many('res.partner', 'church_id', 'Members', domain=[('active','=',True)]),
'church_id': fields.many2one('res.partner', 'Church', domain="[('is_company','=',True)]")
}
What I would like to do, is that when the user opens the church_id view, it shows only partners that are churches. For now, it displays all companies as I am not able to set correctly the domain. A church is a company that has the category id (res.partner.category) corresponding to the church category. I tried to solve my problem using a functional field, but I am only getting some errors. The following function returns correctly a dictionary containing the current user id and the list of the church ids :
# Returns : {'user_id': [church_id1, church_id2, ...]}
def _get_church_ids(self, cr, uid, ids, field_name, arg, context=None):
sql_req = """
SELECT R.partner_id
FROM res_partner_res_partner_category_rel R
LEFT JOIN res_partner_category C ON ( R.category_id = C.id)
WHERE C.active = TRUE AND UPPER(C.name) = 'CHURCH'
"""
cr.execute(sql_req)
sql_res = cr.fetchall()
return dict.fromkeys(ids, sql_res)
Corresponding field and view :
'church_ids': fields.function(_get_church_ids, type="one2many", relation='res.partner', method=True)
<field name="church_ids" invisible="1"/>
I tried the following domains on the view church_id, and I always get the same error :
Uncaught Error: Expected "]", got "(name)"
<field name="church_id" attrs="{'invisible': [('is_company','=',True)]} domain="[('id','in',[church for church in church_ids[id]])]"/>
<field name="church_id" attrs="{'invisible': [('is_company','=',True)]} domain="[('id','in',[church[0] for church in church_ids)]"/>
Any suggestions on how to do this ? I spent already some days trying to figure it out but with no luck. I also tried to do it with a related field but I couldn't understand how to achieve it... Many thanks for your help !
Someone suggested me that the church_id field should be related to a church table, but I just wanted to indicate if a partner record is a church or not. Therefore, I could just create a field called 'is_church' as a boolean, then use a domain to filter for any partner records where the is_church value is set to true like this
domain = "[('is_church','=',True)]"
I can get rid of the church_id field because it's not related to a church table.
In the .py file:
_columns{
'is_church': fields.boolean('Is a Church', domain="[('is_church', '=', True)]")
}
It seems onchange method only works on current visible fields. If I use it to fill other fields that are in other pages of the view, it does not do anything. For example I have view with many pages. Mainly all information needs to be filled in first page, so most fields are filled correctly. But there is one field I need to fill in other page, when I choose partner_id in another page. For example in view like this:
...
<page string="page1">
<field name=partner_id on_change="onchange_partner(partner_id)"
<field name="field1"/>
<field name="field2"/>
</page>
<page string="page2">
<field name="field3"/>
</page>
...
field1 and field2 will be filled. But how to fill field3 or is it impossible, because system do not save it into database using onchange method?
My onchange method looks something like this:
def onchange_partner(self, cr, uid, ids, partner_id, context=None):
res = {}
if partner_id:
obj = self.pool.get('res.partner').browse(cr, uid, partner_id)
res['field1'] = obj.field1
res['field2'] = obj.field2
res['field3'] = obj.field3 # this value isn't being filled
return {'value': res}
So how could I fill field3?
Its not like that. It will definitely change the value. you might not be getting value in field3 because the record you are fetching will not have value of field3. and answer to your question is IT WORKS. Try this,
def onchange_partner(self, cr, uid, ids, partner_id, context=None):
res = {}
if partner_id:
obj = self.pool.get('res.partner').browse(cr, uid, partner_id)
res['field1'] = obj.field1
res['field2'] = obj.field2
res['field3'] = 'Hello' # this field type must be char or if not then give
#value accordingly, its just to prove you that values are filled on onchange.
return {'value': res}
Hope this will help you.