I am working with odoo 10 and have created a few fields, and have the following problem:
I created my own field (x_order_bestelldatum) in the module sale.order. When I confirm an offer, I enter the effective order date in this field.
Now, when I create an invoice, I want to read the x_order_bestelldatum field of the module sale.order in module account.invoice so that I can print the order date on the invoice.
How can I read out the field x_order_bestelldatum from model sale.order in model account.invoice?
Here is my code in file models.py, but it does not work:
from odoo import models, fields, api
class felder_saleorder(models.Model):
_inherit = 'sale.order'
x_order_bestelldatum = fields.Date(string="Bestelldatum")
class felder_invoice(models.Model):
_inherit = 'account.invoice'
sale_order = fields.Many2one('sale.order','sale_order')
x_bestelldatum = fields.Date(string="Bestelldatum",related='sale_order.x_order_bestelldatum')
x_lieferdatum = fields.Date(string="Lieferdatum")
That does not work (the field x_bestelldatum remains empty):
sale_order = fields.Many2one('sale.order','sale_order')
x_bestelldatum = fields.Date(string="Bestelldatum",related='sale_order.x_order_bestelldatum')
Well lets not do it your way plus I can't get it how you are doing it.
So, I am suggesting some other possibilities which might help you.
First lets talk about the sale order field whom you named as 'sale_order'.
There are two possible options with which you are entering data in the sale_order field.
1). Automatically through python
2). Manually by selecting from the list.
In case of entering data Manually you should use onchange function:
#api.onchange('sale_order')
def get_order_date(self):
if self.sale_order:
self.x_bestelldatum = self.sale_order.x_order_bestelldatum
In Case if you are automatically entering data through python then you can use monetary or create function to fill the field.
Create function:
#api.model
def create(self, vals):
new_record = super(felder_invoice, self).create(vals)
if new_record.sale_order:
new_record.x_bestelldatum = new_record.sale_order.x_order_bestelldatum
return new_record
Compute Funtion:
First you need to amend your field deceleration in py file like that
x_bestelldatum = fields.Date(string="Bestelldatum",compute="get_order_date")
Then you need to create a compute function for that:
#api.one
#api.depends('sale_order')
def get_order_date(self):
if self.sale_order:
self.x_bestelldatum = self.sale_order.x_order_bestelldatum
You can get the order date by using above mentioned functions and willbe able to get its value in reports/prints.
Hope it helps.
Cheers!
Thank you for your answer.
I have tried a few variants, but it still does not work. The field 'x_bestelldatum' in the module 'account.invoice' will always be empty.
This is what my code looks like:
class felder_invoice(models.Model):
_inherit = 'account.invoice'
x_lieferdatum = fields.Date(string="Lieferdatum")
sale_order = fields.Many2one('sale.order','sale_order')
x_bestelldatum = fields.Date(string="Bestelldatum",compute="get_order_date")
#api.one
#api.depends('sale_order')
def get_order_date(self):
if self.sale_order:
self.x_bestelldatum = self.sale_order.x_order_bestelldatum
Is that right? Are all fields from 'sale.order' transferred to the new locale field 'sale_order'?
sale_order = fields.Many2one('sale.order','sale_order')
Related
I have this calendar that is made with Javascript.
When you click in "Libre", a view opens, where you can create a reserve. I want the reservation line as default and look something like this. In this case I did it manually, and I want it to appear automatically. I know I need an on #api.onchange function.
The roomid field ("Room" in the image) has the ID of the room that I need to add in reservation.line. I get this from .js
I have something like this in my code and it's getting exactly the room I want, but I don't know how to make it appear automatically.
class HotelReservation(models.Model):
_name = "hotel.reservation"
room_id = fields.Many2one("hotel.room", string="Room", required=True)
roomid= fields.Integer(related='room_id.id', string="Room")
reservation_line = fields.One2many(
"hotel.reservation.line",
"line_id",
string="Reservation Line",
help="Hotel room reservation details.",
readonly=True,
states={"draft": [("readonly", False)]},
)
#api.onchange('roomid')
def onchange_reservation_line(self):
if self.roomid:
room = self.env['hotel.room'].search([('id' ,'=', self.roomid)])
# Some return here?
You can read in the write function documentation that the expected value of a One2many or Many2many relational field is a list of Command that manipulates the relation the implement. There are a total of 7 commands: create(), update(), delete(), unlink(), link(), clear(), and set().
roomid is related to room_id so you can use it in onchange function and avoid calling the search method to get the room record.
Example:
#api.onchange('room_id')
def onchange_reservation_line(self):
if self.room_id:
self.reservation_line = [
Command.clear(),
Command.create({
'field_name': field_value,
...
}),
]
I have two fields in Sale order, i need to get values from each one change its value in text and display in another field in custom model
Two fiedls in sale.order module:
amount_total = fields.Monetary(string="Total", store=True, compute='_compute_amounts', tracking=4)
date_order = fields.Datetime()
and this is my code so far:
from odoo import fields, models, api
from odoo.exceptions import ValidationError
import random
readonly_fields_states = {
state: [('readonly', True)]
for state in {'sale', 'done', 'cancel'}
}
class SaleOrder(models.Model):
_inherit = "sale.order"
test = fields.Many2one(string="Test",
comodel_name='sale.order',
default=lambda x: random.randint(1, 10),
states=readonly_fields_states,
)
#api.constrains('test')
def check_test_length(self):
for rec in self:
if rec.test:
if len(rec.test) > 50:
raise ValidationError('Длина текста строки "test" должна быть меньше 50 символов!')
else:
pass
The goal is: get data from fields turn its type into text and display that data in fiedl test when the two from sale.order is changed. For now i get only names S00001, S00002.. etc.
I have no working solution. I have tried various fucntion but non of them seems to work or i doing something wrong. I realise that my case bit unclear thats because i can`t wrap my head around it. So ask me whatever needed if you want to help.
You can use odoo related field attribute.
In your custom model add a relational field with sale.order and then create related fields.
sale_order_id = fields.Many2one(comodel_name="sale.order")
sale_order_amount_total = fields.Monetary(related="sale_order_id.amount_total")
sale_order_date_order = fields.Datetime(related="sale_order_id.date_order")
Now in custom model views you'll be able to use created fields.
<field name="sale_order_amount_total" />
<field name="sale_order_date_order" />
Note that these fields will be directly related to your Many2one model instance (sale.order record)
Good practice is to set them to readonly=True
In case you are going to execute queries in your custom models using your related fields, you should consider using store=True as attribute.
For example
sale_order_amount_total = fields.Monetary(
related="sale_order_id.amount_total",
store=True,
readonly=True
)
I want to update computed field records but it writes self record in all fields when I use write method.
the name field in product, template is non stored. now because of our business needs so I can't search it.
I make another stored field to move name records into it. so I can looking for instead of name.
I make a button to update data in that field from name field. but when I press the button it updates with self name not name of each product.
class autopart(models.Model):
_inherit = 'product.template'
#api.multi
def button_name(self):
for rec in self:
name=self.name
rec.search([]).write({'nameseacrh': self.name})
name = fields.Char(string="Name", required=False ,compute=compute_amount ,search=pro_search)
nameseacrh = fields.Char(string="", required=False,store=True, compute=compute_search )
button XML
<button name="button_name" type="object" string="name" class="oe_highlight" groups="base.group_system"/>
I don't fully understand what you are trying to do but here are already a few remarks:
#api.multi
def button_name(self):
for rec in self:
name=self.name # remark 1
rec.search([]).write({'nameseacrh': self.name}) # remark 2 and 3
1) You never use this variable
2) rec.search([]) is the same as self.env['product.template'].search([]): It takes all the product templates in the db. You probably didn't want to do that... Then you write your values on all the records.
3) you use self.name instead of rec.name. The first one will work only if self is a recordset of one element, which will not be the case most of the time in an #api.multi
4) I don't get why you would need to make a new field that does what you had before. You shouldn't have to do that.
In Odoo there is a file addons/website_quote/models/sale_order.py which has a class SaleOrder. It has a field
website_description = fields.Html('Description', sanitize_attributes=False, translate=html_translate)
I would like this field to become not translatable, since every time the user saves a record he (the user) gets message "Update translations". Which annoyed the user.
website_description = fields.Html('Description', sanitize_attributes=False, translate=False)
To achieve this I would create another class that inherits SaleOrder and has this line
website_description = fields.Html('Description', sanitize_attributes=False, translate=False)
Is this right way to change field's attribute?
You don't need to recreate all field attributes again with the new API:
from odoo import models, fields
class SaleOrder(models.Model):
_inherit = "sale.order"
website_description = fields.Html(translate=False)
That should be enough.
I am using modelformset_factory to edit multiple images on my interface.
I have following fields in each image.
Name
User
City
I have allowed user to select new user that is currently not in the system, (for that case I should get a text "Jack" in my
def clean_user(self) instead of ID.
But using model_formseta_factory, I am getting some wired names in my self.data. and when I try to get self.data.get('user'), I get nothing, obviously there is no key with this name,
the key is formed like form_0_user etc.
fields = ['city', 'name']
note, i do not have user in my fields. if I do, it fails the validation.
def clean(self):
data = self.cleaned_data
data['name'] = data.get('name', '').strip()
return data
Works fine
pic_credits = self.data.get('user')
This does not.
pic_credits = self.data.get('form-0-name')
This works fine too.
Please help.
If you want to use self.data instead of self.cleaned_data, you can construct the "composite prefix" using the fields auto_id and prefix (or at least when the form has been instanced by a formset).
See _construct_form() https://docs.djangoproject.com/es/1.9/_modules/django/forms/formsets/
Your method will look like this:
def clean(self):
# ...
form_prefix_and_autoid = "%s-%d-" % (self.prefix, self.auto_id)
pic_credits = self.data.get(form_prefix_and_autoid + 'name')
# ...
Update:
A lot simpler is calling the method self.add_prefix
pic_credits = self.data.get(self.add_prefix('name'))