Problems with Odoo 13 Domain filtering - odoo-13

i want to make a price selection for odoo.
I set it as one2many on product.product. It only consists of a field price type and a price.
What i want is the following:
choosable price_types should be apple, peach or lemon
- no price selection records created:
-- domain for type_id is apple, peach or lemon
- 1 record created with type apple:
-- domain for record 1: type_id is apple, peach or lemon
-- domain for new record: type_id is peach or lemon
- second record created with typle peach:
-- domain for record 1: type_id is apple or lemon
-- domain for record 2: type_id is peach or lemon
-- domain for new record: type_id is lemon
- third record created with typle lemon:
-- domain for record 1: type_id is apple
-- domain for record 2: type_id is peach
-- domain for record 3: type_id is lemon
-- new record: no further record could be created as no type_id left
the reason i want to keep the actual selected value per record in the domain is that odoo doesn't seem to like if i remove the currently selected value from the domain
My price selection is below class "product_draft_prices". price_type is the field type_id and the combination (type_id, product_id) has to be unique.
is the above mentioned filtering possible with domain filter ? The price types are stored in the separate table product_draft_pr_types especially for domain filtering.
So i want to set a domain filter on record basis.
I think the closest existing widget for this to refer is the many2manywidget. Here you can also choose only records which are not already assigned.
product Expansion
class product_product(models.Model):
_inherit = 'product.product'
product_draft_prices = fields.One2many('product.product.draft_prices', 'product_id', string='Produktpreise', copy=True, auto_join=True)
Product price table
class product_draft_prices(models.Model):
_name = 'product.product.draft_prices'
_description = 'product.product.draft_prices'
_sql_constraints = [('unique_type', 'unique(type_id, product_id)',
'Fehler bei Produktpreisen:\n\nDieser Preistyp ist ' + \
'für dieses Produkt schon vergeben, bitte anderen auswählen')]
product_id = fields.Many2one('product.product', string='Produkt', required=True, copy=False)
type_id = fields.Many2one('product.product.draft_pr_types', required=True, string="Preistyp")
name = fields.Char('Name des Produktpreises')
price = fields.Float('Preiseingabe', required=True, digits='Product Price')
Product price types
class product_draft_pr_types(models.Model):
_name = 'product.product.draft_pr_types'
_description = 'product.product.draft_pr_types'
types = ['apple', 'peach', 'melon']
name = fields.Char('Preistyp')
Thanks in advance

You can try this.I don't know exactly it will work or not.
I wish even it cannot be solved, you may get some reference.
class product_draft_prices(models.Model):
_name = 'product.product.draft_prices'
_description = 'product.product.draft_prices'
_sql_constraints = [('unique_type', 'unique(type_id, product_id)',
'Fehler bei Produktpreisen:\n\nDieser Preistyp ist ' + \
'für dieses Produkt schon vergeben, bitte anderen auswählen')]
product_id = fields.Many2one('product.product', string='Produkt', required=True, copy=False)
type_id = fields.Many2one('product.product.draft_pr_types', required=True, string="Preistyp")
name = fields.Char('Name des Produktpreises')
price = fields.Float('Preiseingabe', required=True, digits='Product Price')
#api.onchange('type_id','product_id.product_draft_prices')
def onchange_type_id(self):
price_list=[]
for plist in self.product_id.product_draft_prices:
price_list.append(plist.type_id.price_type.id)
return {'domain':{'type_id':[('price_type','not in',price_list)]}}
Change your selection field into many2one.
class product_draft_pr_types(models.Model):
_name = 'product.product.draft_pr_types'
_description = 'product.product.draft_pr_types'
types = field.many2one(product.type,string="Type")
name = fields.Char('Preistyp')
class type(models.Model):
_name = "product.type"
name= field.Char(string="Type name")

so my code looks like this now
class product_draft_prices(models.Model):
_name = 'product.product.draft_prices'
_description = 'product.product.draft_prices'
_sql_constraints = [('unique_type', 'unique(type_id, product_id)',
'Fehler bei Produktpreisen:\n\nDieser Preistyp ist ' + \
'für dieses Produkt schon vergeben, bitte anderen auswählen')]
#api.depends('type_ids','product_id.product_draft_prices')
def _get_type_ids(self):
for record in self:
price_list = []
for plist in record.product_id.product_draft_prices:
if record.type_id and record.type_id.name and record.type_id.name == plist.type_id.name:
continue
price_list.append(plist.type_id.id)
record.type_ids = [(6, 0, price_list)]
product_id = fields.Many2one('product.product', string='Produkt', required=True, copy=False)
type_id = fields.Many2one('product.product.draft_pr_types', required=True, string="Preistyp")
type_ids = fields.Many2many('product.product.draft_pr_types', required=True, string="Preistypen zur Auswahl", store=True, compute=_get_type_ids)
name = fields.Char('Name des Produktpreises')
price = fields.Float('Preiseingabe', required=True, digits='Product Price')
#api.onchange('type_id','product_id.product_draft_prices')
def _onchange_type_id(self):
price_list = []
for plist in self.product_id.product_draft_prices:
if self.type_id and self.type_id.name and self.type_id.name == plist.type_id.name:
continue
price_list.append(plist.type_id.name)
return {'domain': {'type_id': [('name', 'not in', price_list)]}}
and these 2 lines for the view
<field name="type_ids" invisible="1"/>
<field name="type_id" domain="[('id', 'not in', type_ids)]"/>
the domain for field type_id gets overriden at runtime with the currently selected value, so problem solved

The filter_domain attribute can contain an arbitrary domain, so you're restricted neither to searching for the same field you named in the name attribute nor to using only one term.
<record id="account_tax_view_search" model="ir.ui.view">
<field name="name">account.tax.search.filters</field>
<field name="model">account.tax</field>
<field name="arch" type="xml">
<search string="Search Taxes">
<field name="name" filter_domain="['|', ('name','ilike',self), ('description','ilike',self)]" string="Tax"/>
<field name="company_id" groups="base.group_multi_company"/>
</search>
</field>
</record>

Related

Many2many field tableundefined odoo, can't get multiple many2many fields

I have multiple Many2many fields but I'm getting the following error:
relation stream doesn't exist,undefined-table
I cannot find where this error is occurring. Can someone help me fix this error?
class College(models.Model):
_name = 'module5_college'
_description = 'College Info'
_rec_name = 'clg'
clg = fields.Char("College Name")
uni = fields.Char("Affiliated to")
cou = fields.Many2many('module5_stream',string="Stream")
class Stream(models.Model):
_name = 'module5_stream'
_description = 'Stream info'
_rec_name = 'cou'
cou = fields.Selection([
('BTECH', 'BTECH'),
('MTECH', 'MTECH'),
('MCA', 'MCA')],"Stream")
cou_mode = fields.Selection([
('Regular','Regular'),
('Lateral','Lateral'),
('Distance','Distance')],"Course Mode")
sem_no = fields.Integer("No of semesters")
# full_score = fields.Integer(compute='score_calc',string="Score")
sem = fields.Many2many('module5_sem',"Semesters")
class Semester(models.Model):
_name = 'module5_sem'
_rec_name = 'id'
sem_no = fields.Char("Semester No")
sub = fields.Many2many('module5_subject',"Subjects")
You have to follow this example because this is the way to create many2many field:
employees_ids = fields.many2many('Employees.Employees', 'tasks_employees_rel', 'task_id', 'employee_id', 'Employees assigned to task')
To give you a better example.
A employee can be assigned to many tasks
A task can be assigned to many employees
So you have a many2many relation, so that means that you have to create a new table containing both keys.

Text in a class - href statement

How could i get all the categories mentioned on each listing page of the same website "https://www.sfma.org.sg/member/category". for example, when i choose alcoholic beverage category on the above mentioned page, the listings mentioned on that page has the category information like this :-
Catergory: Alcoholic Beverage, Bottled Beverage, Spirit / Liquor / Hard Liquor, Wine, Distributor, Exporter, Importer, Supplier
how can i extract the categories mentioned here with in same variable.
The code i have written for this is :-
category = soup_2.find_all('a', attrs ={'class' :'clink'})
links = [links['href'] for links in category]
cat_name = [cat_name.text.strip() for cat_name in links]
but it is producing the below output which are all the links on the page & not the text with in the href:-
['http://www.sfma.org.sg/about/singapore-food-manufacturers-association',
'http://www.sfma.org.sg/about/council-members',
'http://www.sfma.org.sg/about/history-and-milestones',
'http://www.sfma.org.sg/membership/',
'http://www.sfma.org.sg/member/',
'http://www.sfma.org.sg/member/alphabet/',
'http://www.sfma.org.sg/member/category/',
'http://www.sfma.org.sg/resources/sme-portal',
'http://www.sfma.org.sg/resources/setting-up-food-establishments-in-singapore',
'http://www.sfma.org.sg/resources/import-export-requirements-and-procedures',
'http://www.sfma.org.sg/resources/labelling-guidelines',
'http://www.sfma.org.sg/resources/wsq-continuing-education-modular-programmes',
'http://www.sfma.org.sg/resources/holistic-industry-productivity-scorecard',
'http://www.sfma.org.sg/resources/p-max',
'http://www.sfma.org.sg/event/',
.....]
What i need is the below data for all the listings of all the categories on the base URL which is "https://www.sfma.org.sg/member/category/"
['Ang Leong Huat Pte Ltd',
'16 Tagore Lane
Singapore (787476)',
'Tel: +65 6749 9988',
'Fax: +65 6749 4321',
'Email: sales#alh.com.sg',
'Website: http://www.alh.com.sg/',
'Catergory: Alcoholic Beverage, Bottled Beverage, Spirit / Liquor / Hard Liquor, Wine, Distributor, Exporter, Importer, Supplier'
Please excuse if the question seems to be novice, i am just very new to python,
Thanks !!!
The following targets the two javascript objects housing mapping info about companies names, categories and the shown tags e.g. bakery product. More more detailed info on the use of regex and splitting item['category'] - see my SO answer here.
It handles unquoted keys with hjson library.
You end up with a dict whose keys are the company names (I use permalink version of name, over name, as this should definitely be unique), and whose values are a tuple with 2 items. The first item is the company page link; the second is a list of the given tags e.g. bakery product, alcoholic beverage). The logic is there for you to re-organise as desired.
import requests
from bs4 import BeautifulSoup as bs
import hjson
base = 'https://www.sfma.org.sg/member/info/'
p = re.compile(r'var tmObject = (.*?);')
p1 = re.compile(r'var ddObject = (.*?);')
r = requests.get('https://www.sfma.org.sg/member/category/manufacturer')
data = hjson.loads(p.findall(r.text)[0])
lookup_data = hjson.loads(p1.findall(r.text)[0])
name_dict = {item['id']:item['name'] for item in lookup_data['category']}
companies = {}
for item in data['tmember']:
companies[item['permalink']] = (base + item['permalink'], [name_dict[i] for i in item['category'].split(',')])
print(companies)
Updating for your additional request at end (Address info etc):
I then loop companies dict visiting each company url in tuple item 1 of value for current dict key; extract the required info into a dict, which I add the category info to, then update the current key:value with the dictionary just created.
import requests
from bs4 import BeautifulSoup as bs
import hjson
base = 'https://www.sfma.org.sg/member/info/'
p = re.compile(r'var tmObject = (.*?);')
p1 = re.compile(r'var ddObject = (.*?);')
r = requests.get('https://www.sfma.org.sg/member/category/manufacturer')
data = hjson.loads(p.findall(r.text)[0])
lookup_data = hjson.loads(p1.findall(r.text)[0])
name_dict = {item['id']:item['name'] for item in lookup_data['category']}
companies = {}
for item in data['tmember']:
companies[item['permalink']] = (base + item['permalink'], [name_dict[i] for i in item['category'].split(',')])
with requests.Session() as s:
for k,v in companies.items():
r = s.get(v[0])
soup = bs(r.content, 'lxml')
tel = soup.select_one('.w3-text-sfma ~ p:contains(Tel)')
fax = soup.select_one('.w3-text-sfma ~ p:contains(Fax)')
email = soup.select_one('.w3-text-sfma ~ p:contains(Email)')
website = soup.select_one('.w3-text-sfma ~ p:contains(Website)')
if tel is None:
tel = 'N/A'
else:
tel = tel.text.replace('Tel: ','')
if fax is None:
fax = 'N/A'
else:
fax = fax.text.replace('Fax: ','')
if email is None:
email = 'N/A'
else:
email = email.text.replace('Email: ','')
if website is None:
website = 'N/A'
else:
website = website.text.replace('Website: ','')
info = {
# 'Address' : ' '.join([i.text for i in soup.select('.w3-text-sfma ~ p:not(p:nth-child(n+4) ~ p)')])
'Address' : ' '.join([i.text for i in soup.select('.w3-text-sfma ~ p:nth-child(-n+4)')])
, 'Tel' : tel
, 'Fax': fax
, 'Email': email
,'Website' : website
, 'Categories': v[1]
}
companies[k] = info
Example entry in companies dict:

How to limit the approve action only for the manager of team

I'm using odoo11 and i have installed a custom module to calculate the overtime, i've many team leaders, each team leader has a number of employee.
I want to limit the approve action for the manager in a way every manager approve request of his own employees only.
I have override the approve action to verify if the person who's gone approve is his manager or not but always it allows any manager to approve all the requests. Here is code :
overtime.py
class BtHrOvertime(models.Model):
_name = "bt.hr.overtime"
_description = "Bt Hr Overtime"
_rec_name = 'employee_id'
_order = 'id desc'
employee_id = fields.Many2one('hr.employee', string="Employee")
manager_id = fields.Many2one('hr.employee', string='Manager')
start_date = fields.Datetime('Date check in')
end_date = fields.Datetime('Date check out')
overtime_hours = fields.Float('Overtime Hours')
notes = fields.Text(string='Notes')
state = fields.Selection([('draft', 'Draft'), ('confirm', 'Waiting for Approval'), ('refuse', 'Refused'),
('validate', 'Approved'), ('cancel', 'Cancelled')], default='draft', copy=False)
attendance_id = fields.Many2one('hr.attendance', string='Attendance')
user_id = fields.Many2one('res.users', string='User', related='employee_id.user_id', related_sudo=True,
compute_sudo=True, store=True, default=lambda self: self.env.uid, readonly=True)
parent_id = fields.Many2one('bt.hr.overtime', string='Parent', copy=False)
#api.multi
def action_approve(self):
if (self.employee_id.parent_id.user_id.id != uid):
raise exceptions.UserError(_('You cannot approve.'))
elif self.attendance_id.check_in and self.attendance_id.check_out:
start_date = datetime.datetime.strptime(self.attendance_id.check_in, DEFAULT_SERVER_DATETIME_FORMAT)
end_date = datetime.datetime.strptime(self.attendance_id.check_out, DEFAULT_SERVER_DATETIME_FORMAT)
difference = end_date - start_date
hour_diff = str(difference).split(':')[0]
min_diff = str(difference).split(':')[1]
tot_diff = hour_diff + '.' + min_diff
actual_working_hours = float(tot_diff)
for record in self:
if actual_working_hours > 9:
record.overtime_hours = actual_working_hours - 9
record.start_date = record.attendance_id.check_in
record.end_date = record.attendance_id.check_out
else:
record.overtime_hours = 0
record.start_date = record.attendance_id.check_in
record.end_date = record.attendance_id.check_out
return self.write({'state': 'validate'})
Please use the below code or checking:
if (self.employee_id.parent_id.user_id.id != self.env.user.id):
raise exceptions.UserError(_('You cannot approve.'))
I think that employee_id.parent_id is the manager of the employee. Also please be informed that you can create a new user group
<record id="group_is_manager" model="res.groups">
<field name="name">Is a manager?</field>
</record>
For the Manager users you can check this group and give this group for approve button
<button name="" string="" type="" groups="module_name.group_is_manager"/>
Hence, the button will be visible to those users who have this group.

How can i change a boolean value in model A, when a new instance of model B (have many2one field to model A) is created in ODOO 12?

I have two odoo 12 models,(biblio.location and biblio.book),
-the model "biblio.book" contains a boolean "disponibile" set to true by defaul.
-the model "biblio.location" have a many2one field references to model "biblio.book".
i want the value of the boolean "disponible" in biblio.book to be changed automatically (change also in database) when a new instance of biblio.location is created, in other way when we rent(location) a book we must change disponibility in model book to FALSE.
i tried "computed field, #api.onchange and #api.depends" and nothing works for me, please help me in this issue and i want to know de difference between those three mehods.thank you
class book(models.Model):
_name = 'biblio.book'
_description = 'All books'
name=fields.Char()
annee_edition = fields.Date(string="année d'édition")
ISBN = fields.Integer(required=True)
editor = fields.Char(required=True)
auteur = fields.Many2many('biblio.author',string='auteur_livre',required=True)
disponible=fields.Boolean(default=True,required=True,related='biblio.location.disponible',store=True )
class location(models.Model):
_name = 'biblio.location'
_description = 'All librarians'
name=fields.Char()
livre = fields.Many2one('biblio.book',string='livre',required=True,domain =[('disponible','=',True)])
client = fields.Many2one('biblio.customer',string="client",required=True)
date_location =fields.Datetime(required=True)
date_retour_prevu=fields.Datetime(required=True,string="Date retour prévu")
date_retour_reelle=fields.Datetime(required=True,string="Date retour réelle")
disponible = fields.Boolean(default=False)
File "C:\Users\PycharmProjects\Odoo12\odoo\odoo\fields.py", line 484, in setup_full
self._setup_related_full(model)
File "C:\User\PycharmProjects\Odoo12\odoo\odoo\fields.py", line 527, in _setup_related_full field = target._fields[name]
KeyError: 'biblio' - - -
OK, for this to work the way you want it you need to set up a foreign key in your biblio.book model.
book_location = fields.Many2one('biblio.location', string='Book Location')
Then you can do your computed field
disponible = field.Boolean(compute='_disponible', string='Available for Loan', default=False)
#api.model
def _disponible(self):
for book in self:
book.disponible = True if book.book_location else False
You don't want to set this as storable as you want it to check every time that the field is called. If you set it to storable it will only compute when the record is created.

How to store multiple values in One2many field through odoo website

I have made a Bulk Inquiry form in odoo website. In which the fields category, qty, brand are to be repeated on clicking Click To Select More Products
Webpage Image:
The problem which I am facing is, values of first row are stored in database but fails to store the values for the next product/category and I have to store it in One2many field
Here is my code (controllers.py):
#http.route(['/website_form/'], auth='public', website=True,methods=['POST', 'GET'], csrf=False, type="http")
def bulkorder(self, **kwargs):
if kwargs:
contact_name = kwargs.get('contact_name')
phone = kwargs.get('phone')
email_from = kwargs.get('email_from')
partner_name = kwargs.get('partner_name')
designation = kwargs.get('designation')
gst_no = kwargs.get('gst_no')
name = kwargs.get('name')
description = kwargs.get('description')
category = kwargs.get('category')
quantity = kwargs.get('quantity')
brand = kwargs.get('brand')
select_type = kwargs.get('select_type')
lines = [(0,0,{'category':category,
'quantity':quantity,
'brand':brand})]
user_data = {
'contact_name': contact_name,
'phone': phone,
'email_from': email_from,
'partner_name': partner_name,
'designation': designation,
'gst_no': gst_no,
'name':name,
'description': description,
'select_type': select_type,
'bulk_order_line':lines,
'select_type':select_type,
}
store = http.request.env['bulk.order']
store.create(user_data)
store.bulk_order_line.write({})
return http.local_redirect('/contactus-thank-you')
models.py:
from odoo import models, fields, api,_
from odoo.exceptions import UserError
from odoo import SUPERUSER_ID
class EIndustry_bulkorder(models.Model):
_name = 'bulk.order'
contact_name=fields.Char(string="Full Name")
phone=fields.Char(string="Phone Number", limit=10)
email_from=fields.Char(string="Email")
partner_name=fields.Char(string="Company Name")
designation=fields.Char(string="Designation")
gst_no=fields.Char(string="GST Number")
name=fields.Char(string="Subject")
description=fields.Char(string="Your Question")
category=fields.Char(string="Product/Category")
quantity=fields.Char(string="quantity")
brand=fields.Char(string="Brand/Make")
lead=fields.Char(string="Lead")
select_type=fields.Many2one('bulk.retailer' , string="Profession",
required=True , store = True)
bulk_order_line = fields.One2many('bulk.bulk_order_lines','bulk_order_line_id',
string='Bulk Order Lines')
class retailerType(models.Model):
_name='bulk.retailer'
name = fields.Char(string="Retailer Name")
class BulkOrderLine(models.Model):
_name = 'bulk.bulk_order_lines'
bulk_order_line_id=fields.Many2one('bulk.order','bulk_order_line',
ondelete='cascade', index=True, copy=False)
category=fields.Char(string="Product/Category")
quantity=fields.Char(string="Quantity")
brand=fields.Char(string="Brand")

Resources