i have two module opportunities and job positions .
i am trying to use only one field of "job positions" name Employees in "opportunities" module.
i am new in openerp and have no knowledge about python . so i am using developer option of openerp . i am attaching my both module file .
Is there any attribute of fields or other so my field will use the value of other module values like as :-
crm.lead xml file:-
<field name="name" module="hr.job" />
here module is not using value of "hr.job" and using of "crm.lead" value.
if i used other name it give me "not field found" error.
please expert help me
You seem pretty confused. What you've attached are view files for your modules, for instance one of them is the form view for object named hr.job. This is not as you call it "module files".
What you need to do is create a many2one (or many2many) field from the referenced object you want to the target object you need, meaning adding a field to whatever class's columns you need in the corresponding py file and not view. A very simple example for a class named opportunity_opportunity:
class opportunity_opportunity (osv.osv):
_name = "opportunity.opportunity"
_columns = {
'name' : fields.char('Name', size=64),
'employee_id': fields.many2one('job.position','name')
}
opportunity_opportunity()
you can later add it in the opportunity_view.xml file as any other field:
<field name="employee_id" string="Employee"/>
More importantly, I think you need to seriously first read and understand the developer book: OpenERP 6.1 Developer Book
EDIT: I just noticed you had already posted the same question yesterday here link, this is very frowned upon in stackoverflow. Please take your time to read the openerp documentation before posting questions.
Related
I have been added an field called commission_total, it gets the record id as the commission_total computed field, it worked well when any of depending fields change but i need to run the function on all old date not while creating a new change the depends field
#api.depends('agents','order_line')
def _compute_commission_total(self):
total = 0
for agent in self.agents:
total += agent.agent_commission
self.commission_total = total
_logger.info("COmmisssion total++++++++++++++++++++++++++++")
_logger.info(self.commission_total)
you could use Odoo server action located in the following path
Settings → Technical → Actions → Server Actions
create a new action and make sure that the field Model is set to the correct model, field Action To Do is set to Execute Python Code, the Python Code field would be your code. which would be something like the following:
all_records = env['Model Name'].search([('Add the preferred domain')]) # you will get all records
for item in all_records:
item._compute_commission_total()
# or as suggested by #Dipen Shah, you could use
# word `records` as it's available in the context
for item in records:
item._compute_commission_total()
please note that there are available variables in the context as following:
env: Odoo Environment on which the action is triggered
model: Odoo Model of the record on which the action is triggered; is a void recordset
record: record on which the action is triggered; may be void
records: recordset of all records on which the action is triggered in multi-mode; may be void
useful Python libraries such as time, datetime, dateutil, timezone
log: log(message, level='info'): logging function to record debug information in ir.logging table
Warning: Warning Exception to use with raise
if you would like such action to be a source code within your module. it would be an xml file. it could be in data folder. it would look like:
<record id="action_to_recompute_fields" model="ir.actions.server">
<field name="name">Recompute the fields</field>
<field name="type">ir.actions.server</field>
<field name="model_id" ref="model_YOUR_MODEL_NAME"/>
<field name="state">code</field>
<field name="code">
for item in records:
item._compute_commission_total()
</field>
</record>
or you could make it as Scheduled Actions
according to your latest comment, if you would like to apply this on existing production database, from your module & not manually. you have to use module versioning which is found in __manifest__.py file. so you will increment your module version number. then add migrations folder as suggested from the following website: https://odoo-development.readthedocs.io/en/latest/maintenance/data-migration.html
you could try this. let us know if it is working.
A way to recompute a field is to:
Drop the corresponding database column. You can use psql to run an ALTER TABLE command,
Run module upgrade.
I find this easier to remember and, if you have database access, easier to implement.
Just to preface, I'm using Odoo 10 Enterprise.
I have a custom module with the following (these are just the relevant fields) on its form:
orange_tag_id = This is a Many2Many field with the _Checkboxes widget defined that's connected to a Tags module (we'll just call it orange.tags). This field displays six or seven tags I've created and then applied to various products within the 'product.product/template' module.
orange_child_ids = This is just a One2Many within a child module of the parent module. This lists a product_tmpl_id Many2One and then a read-only copy of orange_tag_id from the parent that just copies whatever is selected in orange_tag_id in the parent form (this was created just in case defining parent.orange_tag_id in the domain didn't work).
When a tag is selected from the orange_tag_id checkbox, it should sort of modify the domain of product_tmpl_id in orange_child_ids and then only display the products in the drop-down display that have been tagged with the selected active tag. I've managed to get this sort of working by just adding the following to the form XML view within orange_child_ids:
<field name="product_tmpl_id" domain="[('orange_tag_id.id','in',parent.orange_tag_id[0])]"/>
This will display only the products that have been tagged with the selected tag with one exception: Tag6's products (just calling it this because its ID was 6) will always display in the drop-down regardless of whether it's selected or not. If Tag2 is selected, then Tag2 and Tag6's products will display. I tried removing Tag6 from any products that had it defined, then deleting the Tag6 record, re-creating the tag, and re-applying it to the relevant products, but the issue persists. I also can only select one tag in the checkbox -- if more than one is selected, I get the following error from product_tmpl_id:
TypeError: not all arguments converted during string formatting
This isn't as big of a deal as not having the correct records displaying, but I'd also like to resolve this, but I'm not entirely sure how.
I've searched for hours and am aware of methods where this can be done in self-hosted installations, however, we're using Odoo 10 Enterprise (I've omitted the required x_ in my aforementioned custom fields just for easier readability), and I have no access to the file system and consequently can't make modifications where that's required. I've been trying to figure this out using just the Developer Tools and my administrative access to the database's settings.
I've messed around a lot with the domain, looked through many questions and forum threads, and what I have was the only thing that worked. Is there any way to get this working correctly within the limitations of Enterprise?
Much obliged.
It appears that adding [2] after the [0] makes everything work and resolves the two issues I was having, so:
<field name="product_tmpl_id" domain="[('orange_tag_id.id','in',parent.orange_tag_id[0][2])]"/>
This will filter the results of the Many2One based on the records selected in the Many2Many field.
While [('orange_tag_id.id','in',parent.orange_tag_id[0][2])] will work, it is extremely obscure.
I advise you to go with [('orange_tag_id.id','in',parent.orange_tag_id.ids)]
I am trying to add new field to product.product model.
What I've done so far is:
Add new field on the following model (From Settings > Database Structure > Models):
product.product
with the following details:
Name: x_product_cost
Field Label: Product Cost
Field Type: Float
and leave the rest to default.
The problem is i am unable to show it on the form. This is the only code that is generated when I tried to edit Form:
View Name: product.product.form
Object: product.product
Inherited View: product.template.common.form
Product Variant
lst_price
I can't use product.template model, since that inherits to product.product
Am i missing something here?
PS: I am trying to temporarily fixed assign-different-cost-on-product-variant bug as specified here
https://github.com/odoo/odoo/issues/1198
Can anyone help me with this?
Actually instead of modifying the model from the Odoo configuration, you should create a custom module, in which you will add the new fields and the new behaviors that you need.
To do so you will have to inherit from the models in the python files to extend them, and you will surely have to modify the views as well, so that your custom fields get displayed.
For reference on how to extend models, create a custom module and create the views, you should refer to the Odoo documentation that you can find here.
As an additional note in case you didn't know, but their is a new API that appeared in the version 8 of Odoo, if you can use it, it is much easier and much nicer.
Sometimes our OpenERP users want to make a small change to a field in a core OpenERP module. For example, they want the product screen's Rack, Row, and Case fields to be longer than 16 characters.
Can I change an existing field without making changes to the module that declared it? I'd rather make the changes using our own custom module, instead of editing the product module itself.
I've got this working, but I'm hoping that someone else knows a cleaner way.
You can inherit the core module's class in your custom module, and then just declare a new field with the same name as the one you want to change. Essentially, just copy the field declaration from the core module, paste it into your custom module, and then make the changes you want. For example, our product_notes module widened the Rack, Row, and Case fields to 255 from the product module's 16.
_columns = {'loc_rack': fields.char('Rack', size=255),
'loc_row': fields.char('Row', size=255),
'loc_case': fields.char('Case', size=255)}
The reason I don't like this is that you now have duplication for all the other attributes of the field. If you change the field length, and then the core module changes the help text, you will still have the old help text. I was hoping that there would be some way when the modules are loading to go in and adjust the field attributes of your parent, but I couldn't find any hooks at the right time.
One change that you can make more easily is the default value of a field. Just declare a default value for a core module's field in your custom module, and it will replace the original default. For example, we changed the defaults for sale_delay and produce_delay from those in the product module.
_defaults = {'sale_delay': lambda *a: 5,
'produce_delay': lambda *a: 0}
In ODOO we can change any attribute of a field using xml.
<field name="loc_rack" position="attributes">
<attribute name="string">Axis</attribute>
</field>
But some case like extending the size of a field its failed.
You need to inherit the product form.
Here you go.
from openerp.osv import fields, osv
class product_product(osv.Model) # <<<v7
_inherit = 'product.product'
_columns = {
'loc_rack': fields.char('Rack', size=<your size>),
'loc_row': fields.char('Row', size=<your size>),
'loc_case': fields.char('Case', size=<your size>)
}
In simple words you just need to override the field and apply your attribute changes it will reflect.
I want to make changes to the purchase order report in OpenERP 6.1. Do I have to go in and make changes to the purchase module, or can I create a new module that will inherit the standard report and override some details.
You can't exactly inherit another report and just override some details, but you can replace a standard report and make all existing links to it launch your new report instead.
Our zaber_purchase module contains some changes to the purchase order report that our users wanted. Here's the purchase_report.xml file that replaces the standard report with ours.
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<report
auto="False"
id="purchase.report_purchase_order"
model="purchase.order"
name="purchase.order.zaber"
rml="zaber_purchase/report/order.rml"
string="Purchase Order"
usage="default"/>
</data>
</openerp>
Since it's not inheriting but replacing the report, you have to duplicate the whole report in your version. Your report's id has to match the original report's id, including the module name. In the example above, the original report has an id of report_purchase_order, and it's part of the purchase module, so your report id must be purchase.report_purchase_order to replace it. The name has to match the name in your version's parser file, and the rml attribute has to point to your version's RML file.
Thanks to mihai for explaining most of this in the OpenERP forum.
Don Kirkby has a good answer, and after banging my head on a wall for an hour, I'd like to expand it. But stackoverflow, in all its wisdom, won't let me comment on it because I don't have enough rep points, so instead, I'll spam the question with an unanswer.
By "The id has to match the original report's id, including the module name," Don means that if foomodule has <report id="fooreport" ...>, then in your module you will need to say <report id="foomodule.fooreport" ...>. This is because the ids declared by each module live in a namespace scoped to that module. If you don't reference the other (the one you are overriding) module's namespace, then you just end up creating a new report with the same name which is Bad.
For kicks, check out the database tables ir_act_report_xml, which has all the reports, and ir_model_data, which associates reports (and everything else) with the id attribute from the XML that defined the thing.
RML parser classes are registered globally as Services. For example the Sale Order parser class is registered in addons/sale/report/sale_order.py with
report_sxw.report_sxw('report.sale.order', 'sale.order', 'addons/sale/report/sale_order.rml', parser=order, header="external")
If you try to create another parser with the same name, you get an error : The report "sale.order" already exists!
A simple way to replace the sale.order parser and use a custom parser class is to remove it from the global service registry with :
from netsvc import Service
del Service._services['report.sale.order']
Here is a full example we used to conditionally hide the Discount column in the sale order report if there is no discount
from sale.report import sale_order
from report import report_sxw
# create a custom parser inherited from sale order parser:
class new_order_parser(sale_order.order):
'''Custom parser with an additional method
'''
def __init__(self, cr, uid, name, context):
super(new_order_parser, self).__init__(cr, uid, name, context=context)
self.localcontext.update({
'has_line_discount': self._has_line_discount,
})
def _has_line_discount(self, order):
return any([l.discount for l in order.order_line])
# remove previous sale.report service :
from netsvc import Service
del Service._services['report.sale.order']
# register the new report service :
report_sxw.report_sxw(
'report.sale.order',
'sale.order',
'addons/path/to/the/sale_order.rml',
parser=new_order_parser
)