I created a view containing some audit attributes:
class audit_performance(osv.Model):
_name = "audit.performance"
_auto = False
_description = "Audit performance Analysis"
_inherit = ["audit", "action"]
def init(self, cr):
tools.drop_view_if_exists(cr, 'audit_performance')
cr.execute("""
CREATE OR REPLACE VIEW audit_performance AS (
SELECT
c.id,
c.name,
count(c.id) as nbr_cases,
c.date_begin ,
c.date_end ,
c.user_id,
c.audit_leader,
c.audit_type,
c.state as audit_state,
c.company_id,
a.state as action_state
FROM
audit c, action a
GROUP BY c.id
)""")
and I created a graph view to see the performance of audits, everything works fine but not when I add action state (I changed to one2many field but it doesn't work).
this is the audit model:
class audit(orm.Model):
_name = "audit"
_description = "Audit"
_inherit = ['mail.thread']
_columns = {
'name': fields.char('Name', size=50),
'imp_opp_ids': fields.one2many(
'action',
'audit_id',
'Related Actions',
),}
it doesn't work, it doesn't recognise the field although it does exist in the model.
this is the error message:
relation "action" does not exist
The objective is to classify the audits by state of its actions (audits with all actions are closed or not yet closed ...) and have an idea of treadet audits.
Related
I have two models (parent and child) with mutual m2o filed(analytic account id). I want to filter the value of the field in the child based on the selected value in the parent ( I want the value to be the same). I have tried to do it using on change but it doesn't work so far. Here is my code:
class logistic(models.Model):
_name = 'logistic.logistic'
_inherit = ['portal.mixin', 'mail.thread', 'mail.activity.mixin']
_description = 'logistic.logistic'
_order = 'id desc'
additional_services_ids = fields.One2many('additional.service.line', 'waybill_id',
string='Services lines')
analytic_account_id = fields.Many2one('account.analytic.account', string='Analytic Account',
index=True,required=True)
#api.onchange('analytic_account_id')
def _analytic_account_id(self):
for rec in self:
return {'domain': {
'additional_services_ids.analytic_account_id': [('analytic_account_id', '=',
rec.analytic_account_id.id)]}}
class AdditionalServicesLine(models.Model):
_name = "additional.service.line"
_description = "Additional services"
waybill_id = fields.Many2one('logistic.logistic', string='Additional Services Entry')
analytic_account_id = fields.Many2one('account.analytic.account', string='Analytic Account',
index=True,required=True)
I have a problem in ODOO 10 with a many2many relationship.
I have extended res.partner this way:
class ResPartner(models.Model):
x_bagsdesign = fields.Many2many('product.product',string='Bags Design',relation='bags_design_manufactur')
then I have extended also product.template model:
class product_template_fields(models.Model):
_inherit = 'product.template'
x_traders_stock = fields.Many2many(
'res.partner', string='Traders with access to stock',relation='xtradstock_res_partner_rel')
#api.multi
def write(self, vals):
record = super(product_template_fields, self).write(vals)
for singletrader in self.x_traders_stock:
singletrader.x_bagsdesign = [(4,self.id)]
return record
This way every time a new x_traders_stock is inserted in product.template, a new x_bags_design is also created in res.partner.
BUT.. when I save a new record in product.template I get an sql error:
bad query: INSERT INTO bags_design_manufactur (res_partner_id, product_product_id)
(SELECT a, b FROM unnest(ARRAY[1]) AS a, unnest(ARRAY[7]) AS b)
EXCEPT (SELECT res_partner_id, product_product_id FROM bags_design_manufactur WHERE res_partner_id IN (1))
I don't understand where the EXCEPT part of the sql query is coming from and how to prevent it. If anyone can help I would be grateful.. thanks!
The error message is a bit different from expected, but I can fix some problems in your code. First of all you have to take into account that a product.product object is a variant of a product.template object, so you can have in a database many product.product objects pointing to the same product.template (e.g. a product.template is a T-shirt and a product.product is a T-shirt colour red size M). This means that you can't try to set the ID of a product.template in a field which is expecting the ID of a product.product, as you're doing here:
singletrader.x_bagsdesign = [(4,self.id)]
Of course, that mistake will not give you the message error you are receiving, there must be something wrong in other part of your code (I guess related to bags_design_manufactur model).
However, to fix the problem I told you above, you should write this:
class product_template_fields(models.Model):
_inherit = 'product.template'
x_traders_stock = fields.Many2many(
comodel_name='res.partner',
string='Traders with access to stock',
relation='xtradstock_res_partner_rel'
)
#api.multi
def write(self, vals):
result = super(product_template_fields, self).write(vals)
for prod_templ in self:
products = self.env['product.product'].search([
('product_tmpl_id', '=', prod_templ.id),
])
for singletrader in prod_templ.x_traders_stock:
singletrader.write({
'x_bagsdesign': [(4, product.id) for product in products],
})
return result
EDIT
product.product inherits from product.template by delegation, this means that every field you create in product.template model is going to be available in product.product objects, so when you are creating the Many2many field x_traders_stock in product.template, you're creating it in product.product too, so you don't need to add records each time a x_trader is generated. Instead you should change your models:
class ResPartner(models.Model):
x_bagsdesign_prod_templ = fields.Many2many(
comodel_name='product.template',
column1='partner_id',
column2='product_tmpl_id',
string='Bags Design',
relation='xtradstock_res_partner_rel'
)
class ProductTemplate(models.Model):
_inherit = 'product.template'
x_traders_stock = fields.Many2many(
comodel_name='res.partner',
column1='product_tmpl_id',
column2='partner_id',
string='Traders with access to stock',
relation='xtradstock_res_partner_rel'
)
And then, if you want to access to the product.product objects a partner has, you can do it this way:
any_partner.x_bagsdesign_prod_templ.mapped('product_variant_ids')
If you preferred it, you could even create a new related field in res.partner which brought the product.product objects a partner has.
I have these four classes named roster_time, roster_type, roster_allocation and roster_substitution and each class connect with one to many relationship except roster_substitution.
class roster_time(osv.osv):
_name="roster.time"
_description = "To create roster time slot"
_columns={
'roster_id':fields.integer('Roster ID'),
'start_time': fields.char('Start Time',required=True),
'end_time':fields.char('End Time',required=True),
'rostertype':fields.many2one('roster.type','roster','Roster Time'),
'name':fields.char('Roster Time'),
}
roster_time()
Roster Definition class
class roster_type(osv.osv):
_name="roster.type"
_description = "To create roster type for each department"
_columns={
'name': fields.char('Roster type'),
'roster':fields.one2many('roster.time','rostertype','Time Slot'),
'allocation_id':fields.many2one('roster.allocation','Roster ID'),
'roster_time':fields.many2one('roster.time','Slot'),
'roster_end':fields.related('roster.time','roster_start',type='char',string='End Time'),
'allocation_start_day':fields.date('Start Date' ),
'allocation_end_day':fields.date('End Date'),
'department_id':fields.many2one('hr.department','Department',required=True),
}
roster_time()
Roster allocation class
class roster_allocation(osv.osv):
_name="roster.allocation"
_description ="Allocate rosters on employees"
_columns={
'emp_id':fields.many2one('hr.employee','Employee',required=True),
'department_id':fields.many2one('hr.department','Department',required=True),
#'roster':fields.many2one('roster.type','roster', 'Roster ID'),
'roster_linked_ids':fields.one2many('roster.type','allocation_id','Roster Linked Ids'),
'roster_type':fields.related('roster.type','department_id', type='char', string='Roster Type'),
'roster_time':fields.char('Take the related field roster_time.name'),
'monthly allocation':fields.char('Month') ,
'roster_rest_allocation':fields.one2many('roster.rest.days','roster_id','Rest Days'),
'roster_substitute':fields.one2many('roster.substitution','allocation_id','Substitution'),
}
roster_allocation()
Roster Cancellation class
class roster_substitution(osv.osv):
_name="roster.substitution"
_description="Substituting employees "
_columns={
'allocation_id':fields.many2one('roster.allocation','Allocation'),
'employee':fields.many2one('hr.employee','Employee'),
'sub_employee':fields.many2one('hr.employee','Employee'),
'time_slot':fields.many2one('roster.time','Roster'),
'roster_day':fields.date('Day'),
'reason':fields.text('Reason'),
'department_id':fields.many2one('hr.department','Department'),
}
roster_substitution()
What I trying to do is once I cancel a allocation using roster_substitution class I want that record in with the newly allocated person in roster_allocation table using the selected date and time. How to do that
this is my attempt to do it and it's obviously not working
def allocation_substitute(self,cr,uid,ids,roster_day,context=None):
sub_day=vals.get(roster_day)
sub_time_slot=vals.get(time_slot)
allocation_obj=self.pool.get('roster.allocation')
original_employee_id = allocation_obj.browse(cr,uid, values['emp_id']).id
original_employee_roster=allocation_obj.browse(cr,uid, original_employee_id).roster_type
values={'emp_id':'employee',
'department_id':'department_id',
}
allocation_id=allocation_obj.create(cr, uid, value, context=context)
return True
The emp_id and department_id from the object roster.allocation are both many2one field. When passing value to write/create the value should be the database identifier of the record to set, in this case it's the id to hr.employeefor emp_id and hr.department for department_id.
for example:
def allocation_substitute(self,cr,uid,ids,roster_day,context=None):
sub_day=vals.get(roster_day)
sub_time_slot=vals.get(time_slot)
allocation_obj=self.pool.get('roster.allocation')
original_employee_id = allocation_obj.browse(cr,uid, values['emp_id']).id
original_employee_roster=allocation_obj.browse(cr,uid, original_employee_id).roster_type
emp_id = 1 # Search from hr.employee
department_id = 1 # Search from hr.department
values={'emp_id': emp_id,
'department_id': department_id,
}
allocation_id=allocation_obj.create(cr, uid, value, context=context)
return True
I have asset.asset there i have added place1 many2one fields i will create some records through this form .
my requirement is that when i select any location in calendar.event at place the my next field should get only those records which are related to same location
suppose i have created at asset.asset like
1)
name: A1,
place:**karnataka/gulbarga/shahapur
**asset_catg_id:**hardware
**area_id:**hard disk
**asset_modelid_add: qqqq(predifined at other class or model with domain fielter by model_no+make)
**folio_no:**qqqqshahapur(auto populate by combaining location+assermodelid_add)
2)
name: B1,
place:**karnataka/gulbarga/jewargi,
**asset_catg_id:**software
**area_id:**os
**asset_modelid_add: zzzz(predifined at other class or model with domain fielter by model_no+make)
**folio_no:**zzzzjewargi(auto populate by combaining location+assermodelid_add)
i want in calendar.event inherited class when i select location the next field should get asset_modelid_add for that record only i.e in many2many fields like If A1 selected next field should get only karnataka/gulbarga/shahapur ,folio_num as qqqqshahapur
class asset_asset(osv.osv):
_inherit = "asset.asset"
#_name = "asset_asset"
_rec_name= "folio_num"
_columns = {
'name': fields.char('Asset Name', size=64),
'place1': fields.many2one('asset.parentlocation', 'Location'),
'asset_catg_id' : fields.many2one('asset.catg', 'Asset Catg Selection',select=True, required=True),
'area_id' : fields.many2one('asset.name', 'Asset Name Selection', domain="[('asset_catg_id', '=', asset_catg_id)]", select=True, required=True),
'assetmodelid_add' : fields.many2one('agile.portfolio1','Asset Model Code',domain="[('area_id', '=', area_id)]",),
'folio_num' : fields.char('Folio No',),
'asse_line':fields.one2many('asset.line','emp_id','Name Plate'),
'asse_line2':fields.one2many('asset.part','emp_id1','Parts'),
#'assed_modelid':fields.many2one('agile.portfolio1','Asset Model ID',select=True, required=True),
'quantity': fields.char('Quantity',size=64),
'uom': fields.char('Uinit of Measure',size=64),
'model_no' : fields.char('Model', size=64),
#'asset_id':fields.many2one('agile.portfolio','Asset ID'),
}
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
**calendar_event.py**
class calendar_event(osv.osv):
_inherit = "calendar.event"
_rec_name = 'number'
_columns = {
'number' : fields.char('Meeting ID',readonly=1),
'place' : fields.many2one('asset.parentlocation','Substation Location',),
'assetmodelid_add' : fields.many2many('agile.portfolio1','Asset Model Code',),
'folio_num' : fields.many2many('asset.asset','asset_asset_rel','super_id','asset_asset_id','Folio Num',),
'inspection_name' : fields.many2many('asset1.inspection','asset1_inspection_rel','super_id','asset1_inspection_id','Inspection Type'),
}
please update answers how to do with sql or onchage both are acceptable
Lets consider a simple example. Suppose we have a many2one field to Product (name: product_id). We now want to change the content on this many2one field based on type selection box(name: type). Now, if I choose type as Service, only service type product should be visible in Product field.
To accomplish this, we have to define on change function on type selection box.
def onchange_type(self,cr,uid,ids, type,context=None):
product_obj = self.pool.get('product.product')
product_ids = product_obj.search(cr,uid, [('type','=',type)])
return {'domain':{'product_id':[('id','in',product_ids)]}}
In your case you will have to replicate above scenario.. Above case I have used in my project.
thanks,
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.