Porting addon from Odoo 9 to Odoo 10 - ProgrammingError: can't adapt type 'account.tax' - odoo

While trying to reuse this Odoo 9 addon https://www.odoo.com/apps/modules/9.0/purchase_recurring_orders/ | github code to Odoo 10, I am facing the following issue:
File "/usr/lib/python2.7/dist-packages/odoo/custom_addons/purchase_recurring_orders/models/recurring_orders.py", line 310, in generate_initial_order
order = self.create_order(self.start_date, agreement_lines)
...
ProgrammingError: can't adapt type 'account.tax'
Full error can be seen here:
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/odoo/http.py", line 640, in _handle_exception
return super(JsonRequest, self)._handle_exception(exception)
File "/usr/lib/python2.7/dist-packages/odoo/http.py", line 677, in dispatch
result = self._call_function(**self.params)
File "/usr/lib/python2.7/dist-packages/odoo/http.py", line 333, in _call_function
return checked_call(self.db, *args, **kwargs)
File "/usr/lib/python2.7/dist-packages/odoo/service/model.py", line 101, in wrapper
return f(dbname, *args, **kwargs)
File "/usr/lib/python2.7/dist-packages/odoo/http.py", line 326, in checked_call
result = self.endpoint(*a, **kw)
File "/usr/lib/python2.7/dist-packages/odoo/http.py", line 935, in __call__
return self.method(*args, **kw)
File "/usr/lib/python2.7/dist-packages/odoo/http.py", line 506, in response_wrap
response = f(*args, **kw)
File "/usr/lib/python2.7/dist-packages/odoo/addons/web/controllers/main.py", line 889, in call_button
action = self._call_kw(model, method, args, {})
File "/usr/lib/python2.7/dist-packages/odoo/addons/web/controllers/main.py", line 877, in _call_kw
return call_kw(request.env[model], method, args, kwargs)
File "/usr/lib/python2.7/dist-packages/odoo/api.py", line 681, in call_kw
return call_kw_multi(method, model, args, kwargs)
File "/usr/lib/python2.7/dist-packages/odoo/api.py", line 672, in call_kw_multi
result = method(recs, *args, **kwargs)
File "/usr/lib/python2.7/dist-packages/odoo/custom_addons/purchase_recurring_orders/models/recurring_orders.py", line 310, in generate_initial_order
order = self.create_order(self.start_date, agreement_lines)
File "/usr/lib/python2.7/dist-packages/odoo/custom_addons/purchase_recurring_orders/models/recurring_orders.py", line 259, in create_order
order_line_obj.create(order_line_vals)
File "/usr/lib/python2.7/dist-packages/odoo/addons/purchase/models/purchase.py", line 557, in create
line = super(PurchaseOrderLine, self).create(values)
File "/usr/lib/python2.7/dist-packages/odoo/models.py", line 3830, in create
record = self.browse(self._create(old_vals))
File "/usr/lib/python2.7/dist-packages/odoo/models.py", line 3987, in _create
field.write(self.with_context(rel_context), vals[name])
File "/usr/lib/python2.7/dist-packages/odoo/fields.py", line 2402, in write
link(act[2])
File "/usr/lib/python2.7/dist-packages/odoo/fields.py", line 2367, in link
cr.execute(query, (records.ids, list(sub_ids), tuple(records.ids)))
File "/usr/lib/python2.7/dist-packages/odoo/sql_db.py", line 154, in wrapper
return f(self, *args, **kwargs)
File "/usr/lib/python2.7/dist-packages/odoo/sql_db.py", line 231, in execute
res = self._obj.execute(query, params)
•ProgrammingError: can't adapt type 'account.tax'
So far I did not modify anything else than the group use.
This is the code of recurring_orders:
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
# Copyright (C) 2009-TODAY Cybrosys Technologies(<http://www.cybrosys.com>).
# Author: Jesni Banu(<http://www.cybrosys.com>)
# you can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# It is forbidden to publish, distribute, sublicense, or sell copies
# of the Software or modified copies of the Software.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# GENERAL PUBLIC LICENSE (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from datetime import timedelta
from datetime import datetime
from dateutil.relativedelta import relativedelta
from openerp import models, fields, api, exceptions, _
import openerp.addons.decimal_precision as dp
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
class Agreement(models.Model):
_name = 'purchase.recurring_orders.agreement'
_inherit = ['mail.thread']
_description = "Recurring orders agreement"
#api.model
def __get_next_term_date(self, date, unit, interval):
if unit == 'days':
return date + timedelta(days=interval)
elif unit == 'weeks':
return date + timedelta(weeks=interval)
elif unit == 'months':
return date + relativedelta(months=interval)
elif unit == 'years':
return date + relativedelta(years=interval)
#api.multi
def _compute_next_expiration_date(self):
for agreement in self:
if agreement.prolong == 'fixed':
agreement.next_expiration_date = agreement.end_date
elif agreement.prolong == 'unlimited':
now = fields.Date.from_string(fields.Date.today())
date = self.__get_next_term_date(
fields.Date.from_string(agreement.start_date),
agreement.prolong_unit, agreement.prolong_interval)
while date < now:
date = self.__get_next_term_date(
date, agreement.prolong_unit,
agreement.prolong_interval)
agreement.next_expiration_date = date
else:
agreement.next_expiration_date = self.__get_next_term_date(
fields.Date.from_string(agreement.last_renovation_date or
agreement.start_date),
agreement.prolong_unit, agreement.prolong_interval)
def _default_company_id(self):
company_model = self.env['res.company']
company_id = company_model._company_default_get('purchase')
return company_model.browse(company_id.id)
name = fields.Char(
string='Name', size=100, index=True, required=True,
help='Name that helps to identify the agreement')
number = fields.Char(
string='Agreement number', index=True, size=32, copy=False,
help="Number of agreement. Keep empty to get the number assigned by a "
"sequence.")
active = fields.Boolean(
string='Active', default=True,
help='Unchecking this field, quotas are not generated')
partner_id = fields.Many2one(
comodel_name='res.partner', string='Supplier', index=True,
change_default=True, required=True,
help="Supplier you are making the agreement with")
company_id = fields.Many2one(
comodel_name='res.company', string='Company', required=True,
help="Company that signs the agreement", default=_default_company_id)
start_date = fields.Date(
string='Start date', index=True, copy=False,
help="Beginning of the agreement. Keep empty to use the current date")
prolong = fields.Selection(
selection=[('recurrent', 'Renewable fixed term'),
('unlimited', 'Unlimited term'),
('fixed', 'Fixed term')],
string='Prolongation', default='unlimited',
help="Sets the term of the agreement. 'Renewable fixed term': It sets "
"a fixed term, but with possibility of manual renew; 'Unlimited "
"term': Renew is made automatically; 'Fixed term': The term is "
"fixed and there is no possibility to renew.", required=True)
end_date = fields.Date(
string='End date', help="End date of the agreement")
prolong_interval = fields.Integer(
string='Interval', default=1,
help="Interval in time units to prolong the agreement until new "
"renewable (that is automatic for unlimited term, manual for "
"renewable fixed term).")
prolong_unit = fields.Selection(
selection=[('days', 'days'),
('weeks', 'weeks'),
('months', 'months'),
('years', 'years')],
string='Interval unit', default='years',
help='Time unit for the prolongation interval')
agreement_line = fields.One2many(
comodel_name='purchase.recurring_orders.agreement.line',
inverse_name='agreement_id', string='Agreement lines')
order_line = fields.One2many(
comodel_name='purchase.order', copy=False, inverse_name='agreement_id',
string='Orders', readonly=True)
renewal_line = fields.One2many(
comodel_name='purchase.recurring_orders.agreement.renewal', copy=False,
inverse_name='agreement_id', string='Renewal lines', readonly=True)
last_renovation_date = fields.Date(
string='Last renovation date',
help="Last date when agreement was renewed (same as start date if not "
"renewed)")
next_expiration_date = fields.Date(
compute="_compute_next_expiration_date", string='Next expiration date')
state = fields.Selection(
selection=[('empty', 'Without orders'),
('first', 'First order created'),
('orders', 'With orders')],
string='State', readonly=True, default='empty')
renewal_state = fields.Selection(
selection=[('not_renewed', 'Agreement not renewed'),
('renewed', 'Agreement renewed')],
string='Renewal state', readonly=True, default='not_renewed')
notes = fields.Text('Notes')
_sql_constraints = [
('number_uniq', 'unique(number)', 'Agreement number must be unique !'),
]
#api.constrains('start_date', 'end_date')
def _check_dates(self):
for record in self:
if record.end_date and record.end_date < record.start_date:
raise exceptions.Warning(
_('Agreement end date must be greater than start date'))
#api.model
def create(self, vals):
if not vals.get('start_date'):
vals['start_date'] = fields.Date.today()
if not vals.get('number'):
vals['number'] = self.env['ir.sequence'].get(
'purchase.r_o.agreement.sequence')
return super(Agreement, self).create(vals)
#api.multi
def write(self, vals):
value = super(Agreement, self).write(vals)
if (any(vals.get(x) is not None for x in
['active', 'number', 'agreement_line', 'prolong', 'end_date',
'prolong_interval', 'prolong_unit', 'partner_id'])):
self.unlink_orders(fields.Date.today())
return value
#api.model
def copy(self, id, default=None):
agreement_record = self.browse(id)
default.update({
'state': 'empty',
'active': True,
'name': '%s*' % agreement_record['name'],
})
return super(Agreement, self).copy(id, default=default)
#api.multi
def unlink(self):
for agreement in self:
if any(agreement.mapped('order_line')):
raise exceptions.Warning(
_('You cannot remove agreements with confirmed orders!'))
self.unlink_orders(fields.Date.from_string(fields.Date.today()))
return models.Model.unlink(self)
#api.multi
def onchange_start_date(self, start_date=False):
if not start_date:
return {}
result = {'value': {'last_renovation_date': start_date}}
return result
#api.model
def revise_agreements_expirations_planned(self):
for agreement in self.search([('prolong', '=', 'unlimited')]):
if agreement.next_expiration_date <= fields.Date.today():
agreement.write({'prolong': 'unlimited'})
return True
#api.model
def _prepare_purchase_order_vals(self, agreement, date):
order_vals = {
'date_order': date,
'date_confirm': date,
'origin': agreement.number,
'partner_id': agreement.partner_id.id,
'state': 'draft',
'company_id': agreement.company_id.id,
'from_agreement': True,
'agreement_id': agreement.id,
'location_id': 1,
'fiscal_position_id': self.env['account.fiscal.position'].with_context(company_id=agreement.company_id.id).get_fiscal_position(agreement.partner_id.id),
'payment_term_id': agreement.partner_id.property_supplier_payment_term_id.id,
'currency_id': agreement.partner_id.property_purchase_currency_id.id or self.env.user.company_id.currency_id.id,
}
order_vals['user_id'] = agreement.partner_id.user_id.id
return order_vals
#api.model
def _prepare_purchase_order_line_vals(self, agreement_line, order):
product_lang = agreement_line.product_id.with_context({
'lang': order.partner_id.lang,
'partner_id': order.partner_id.id,
})
fpos = order.fiscal_position_id
order_line_vals = {
'order_id': order.id,
'product_id': agreement_line.product_id.id,
'product_qty': agreement_line.quantity,
'date_planned': datetime.today().strftime(DEFAULT_SERVER_DATETIME_FORMAT),
'price_unit': 0.0,
'product_qty': 1.0,
'product_uom': agreement_line.product_id.uom_po_id.id or agreement_line.product_id.uom_id.id,
'name': product_lang.display_name,
'taxes_id': fpos.map_tax(agreement_line.product_id.supplier_taxes_id.filtered(lambda r: r.company_id.id == self.company_id.id))
}
if agreement_line.specific_price:
order_line_vals['price_unit'] = agreement_line.specific_price
order_line_vals['taxes_id'] = [(6, 0, tuple(order_line_vals['taxes_id']))]
if agreement_line.additional_description:
order_line_vals['name'] += " %s" % (
agreement_line.additional_description)
return order_line_vals
#api.multi
def create_order(self, date, agreement_lines):
self.ensure_one()
order_line_obj = self.env['purchase.order.line'].with_context(
company_id=self.company_id.id)
order_vals = self._prepare_purchase_order_vals(self, date)
order = self.env['purchase.order'].create(order_vals)
for agreement_line in agreement_lines:
order_line_vals = self._prepare_purchase_order_line_vals(
agreement_line, order)
order_line_obj.create(order_line_vals)
agreement_lines.write({'last_order_date': fields.Date.today()})
if self.state != 'orders':
self.state = 'orders'
return order
#api.multi
def _get_next_order_date(self, line, start_date):
self.ensure_one()
next_date = fields.Date.from_string(self.start_date)
while next_date <= start_date:
next_date = self.__get_next_term_date(
next_date, line.ordering_unit, line.ordering_interval)
return next_date
#api.multi
def generate_agreement_orders(self, start_date, end_date):
self.ensure_one()
if not self.active:
return
lines_to_order = {}
exp_date = fields.Date.from_string(self.next_expiration_date)
if exp_date < end_date and self.prolong != 'unlimited':
end_date = exp_date
for line in self.agreement_line:
if not line.active_chk:
continue
next_order_date = self._get_next_order_date(line, start_date)
while next_order_date <= end_date:
if not lines_to_order.get(next_order_date):
lines_to_order[next_order_date] = self.env[
'purchase.recurring_orders.agreement.line']
lines_to_order[next_order_date] |= line
next_order_date = self._get_next_order_date(
line, next_order_date)
dates = lines_to_order.keys()
dates.sort()
for date in dates:
order = self.order_line.filtered(
lambda x: (
fields.Date.to_string(
fields.Datetime.from_string(x.date_order)) ==
fields.Date.to_string(date)))
if not order:
self.create_order(
fields.Date.to_string(date), lines_to_order[date])
#api.multi
def generate_initial_order(self):
self.ensure_one()
agreement_lines = self.mapped('agreement_line').filtered('active_chk')
order = self.create_order(self.start_date, agreement_lines)
self.write({'state': 'first'})
order.signal_workflow('order_confirm')
return {
'domain': "[('id', '=', %s)]" % order.id,
'view_type': 'form',
'view_mode': 'form',
'res_model': 'purchase.order',
'context': self.env.context,
'res_id': order.id,
'view_id': [self.env.ref('purchase.purchase_order_form').id],
'type': 'ir.actions.act_window',
'nodestroy': True
}
#api.model
def generate_next_orders_planned(self, years=1, start_date=None):
if start_date:
start_date = fields.Date.from_string(start_date)
self.search([]).generate_next_orders(
years=years, start_date=start_date)
#api.multi
def generate_next_year_orders(self):
return self.generate_next_orders(years=1)
#api.multi
def generate_next_orders(self, years=1, start_date=None):
if not start_date:
start_date = fields.Date.from_string(fields.Date.today())
end_date = start_date + relativedelta(years=years)
for agreement in self:
agreement.generate_agreement_orders(start_date, end_date)
return True
#api.model
def confirm_current_orders_planned(self):
tomorrow = fields.Date.to_string(
fields.Date.from_string(fields.Date.today()) + timedelta(days=1))
orders = self.env['purchase.order'].search([
('agreement_id', '!=', False),
('state', 'in', ('draft', 'sent')),
('date_order', '<', tomorrow)
])
for order in orders:
order.signal_workflow('order_confirm')
#api.multi
def unlink_orders(self, start_date):
orders = self.mapped('order_line').filtered(
lambda x: (x.state in ('draft', 'sent') and
x.date_order >= start_date))
orders.unlink()
class AgreementLine(models.Model):
_name = 'purchase.recurring_orders.agreement.line'
uom_id = fields.Many2one('product_uom', string="Uom")
active_chk = fields.Boolean(
string='Active', default=True,
help='Unchecking this field, this quota is not generated')
agreement_id = fields.Many2one(
comodel_name='purchase.recurring_orders.agreement',
string='Agreement reference', ondelete='cascade')
product_id = fields.Many2one(
comodel_name='product.product', string='Product', ondelete='set null',
required=True)
name = fields.Char(
related="product_id.name", string='Description', store=False)
additional_description = fields.Char(
string='Add. description', size=30,
help='Additional description that will be added to the product '
'description on orders.')
quantity = fields.Float(
string='Quantity', required=True, help='Quantity of the product',
default=1.0)
discount = fields.Float(string='Discount (%)', digits=(16, 2))
ordering_interval = fields.Integer(
string='Interval', required=True, default=1,
help="Interval in time units for making an order of this product")
ordering_unit = fields.Selection(
selection=[('days', 'days'),
('weeks', 'weeks'),
('months', 'months'),
('years', 'years')],
string='Interval unit', required=True, default='months')
last_order_date = fields.Date(
string='Last order', help='Date of the last Purchase order generated')
specific_price = fields.Float(
string='Specific price', digits_compute=dp.get_precision('Purchase Price'),
help='Specific price for this product. Keep empty to use the list '
'price while generating order')
list_price = fields.Float(
related='product_id.list_price', string="List price", readonly=True)
_sql_constraints = [
('line_qty_zero', 'CHECK (quantity > 0)',
'All product quantities must be greater than 0.\n'),
('line_interval_zero', 'CHECK (ordering_interval > 0)',
'All ordering intervals must be greater than 0.\n'),
]
#api.multi
def onchange_product_id(self, product_id=False):
result = {}
if product_id:
product = self.env['product.product'].browse(product_id)
if product:
result['value'] = {'name': product['name']}
return result
class AgreementRenewal(models.Model):
_name = 'purchase.recurring_orders.agreement.renewal'
agreement_id = fields.Many2one(
comodel_name='purchase.recurring_orders.agreement',
string='Agreement reference', ondelete='cascade', select=True)
date = fields.Date(string='Date', help="Date of the renewal")
comments = fields.Char(
string='Comments', size=200, help='Renewal comments')
I have found that this post might be relevant for this issue:
https://github.com/adhoc-dev/odoo-addons/issues/113
I have suspected that this line:
'taxes_id': fpos.map_tax(agreement_line.product_id.supplier_taxes_id.filtered(lambda r: r.company_id.id == self.company_id.id))
might be the issue so I used a print statement:
print fpos.map_tax(agreement_line.product_id.supplier_taxes_id.filtered(lambda r: r.company_id.id == self.company_id.id))
account.tax(6,)
But I do not know how to continue further.
Any help/tip on where the issue could be is welcomed.

The below code
fpos.map_tax(agreement_line.product_id.supplier_taxes_id.filtered(lambda r: r.company_id.id == self.company_id.id))
returns a recordset but database doesn't store record set. that's why it fails with the message.
ProgrammingError: can't adapt type 'account.tax'
Solution
recordset.id // for singleton recordset
result : id (integer)
recordset.ids // for multi recordset
result : list of ids []
now it depends on which type of field you are going to write this value. If it is a Many2one field then it is supposed to be an integer. that you may get with recordset.id
NOTE 1 -
Be careful recordset can be recordsets that means mutliple records that will look like account.tax(6,7,12,34). In this case if you say recordset.id, it will fail because there are multiple Ids and it is not sure which one you want. So to get IDs from the recordset you can do recordset.ids that would result a list like [6,7,12,34] or [] in case a blank recordset.
NOTE2 -
If you were trying to write in a Many2many field. You can do something like
self.taxes_id = [(6,0, recordset.ids)]

Related

Condition while creating Product in Module, Odoo

I have an Inventory module. I want to check db before creating data. Check for reference code. If ref_code already exist then cancel the creation.
This is my .py file:
ref_code = fields.Char(string="Referans Numarası: ", required=True, tracking=True, related="products_id.ref_no")
#product_name = fields.Char(string="Ürün Adı: ", required=True, tracking=True)
product_description = fields.Char(string="Ürün Tanımı: ", tracking=True,)
teslim_alan = fields.Char(string="Teslim Alan: ", required=True, tracking=True,)
teslim_eden = fields.Char(string="Teslim Eden: ", required=True, tracking=True,)
quantity = fields.Float(string="Miktar: ", required=True, tracking=True)
price = fields.Float(string="Fiyat(€): ", required=True, tracking=True, related="products_id.unit_price")
unit_price = fields.Float(string="Birim Fiyat(€): ", compute="_unitPriceCalcuteFunc")
scrap_quantity = fields.Float(string="Hurdaya Taşınacak Miktar: ")
warehouse_id = fields.Many2one('ware.houses', string='Depo Adı: ')
products_id = fields.Many2one('products', string='Ürün: ')
state = fields.Selection([
('unapproved', 'Çıkış İçin Onay Verilmedi.'),
('approved', 'Çıkış İçin Onay verildi.')], string="Status", default="unapproved", tracking=True)
cikis_line_ids = fields.One2many('inventory.out.report.lines', 'inventory_id', string='Çıkış Listesi')
#api.model
def create(self, values):
global count
count = 0
value = self.env['inventory.menu'].search([])
for record in values:
for v in value:
print(v.ref_code, record.ref_code)
if(v.ref_code == record.ref_code):
count += 1
return print("Zaten Var!")
if(count == 0):
return super(InventoryMenu, self).create(values)
I can find the all data in db. It is ok. But the current data is not exist, i can't use it. I need the compare current data with db data.
How can i do it? Many thanks..
#api.model
def create(self, values):
global count
count = 0
value = self.env['inventory.menu'].search([])
for v in value:
if(v.ref_code == values['ref_code']):
count += 1
return print("Zaten Var!")
if(count == 0):
return super(InventoryMenu, self).create(values)
enter code here
You can search for the specific ref_code. Just didn't do something like search([]) cause it's contrproductive.
#api.model
def create(self, values):
ref_codes_count = self.env['inventory.menu'].search(
[("ref_code", "=", values.get("ref_code"))],
count=True,
)
if not ref_codes_count:
return super(InventoryMenu, self).create(values)
or you can try to use something like this
#api.model
def create(self, values):
self.env.cr.execute(
"SELECT COUNT(*) FROM module_name.model_name WHERE ref_code='%s'" %
values.get("ref_code")
)
ref_codes_count = self.env.cr.fetchall()[0]
if not ref_codes_count:
return super(InventoryMenu, self).create(values)

ValueError: Expected singleton: daily.attendance.line(123,124,125

#api.model
def create(self, vals):
curr = datetime.now()
new_date = datetime.strftime(curr, '%Y-%m-%d')
cal_obj = self.env['daily.attendance'].search([])
#api.constrains('date')
def _date_test_unique(self):
for rec in self:
if self.search_count([('date', '=', rec.date)]) > 1:
raise ValidationError(_('Current Date Attendance Already Existed!'))
#api.onchange('user_id')
def onchange_department(self):
if self.user_id == True:
emps = self.env['hr.employee'].search([])
emp_attd = []
from datetime import datetime
now = datetime.now() # current date and time
check_in = now.strftime('%Y-%m-%d %H:%M:%S')
check_in_from = now.strftime('%Y-%m-%d 05:30')
check_out = now.strftime('%Y-%m-%d %H:%M:%S')
check_out_from = now.strftime('%Y-%m-%d 14:30')
for emp in emps:
vals = {
'employe_id':emp.id,
'check_in': check_in_from,
'check_out': check_out_from,
'is_present': True
}
emp_attd.append([0, 0, vals])
self.update({
'employee_ids': emp_attd,
})
else:
self.employee_ids = False
return {
'type': 'ir.actions.client',
'tag': 'reload',
}
The error happens when Odoo tries to get employee_ids value from a record set but it expects a record.
for emp in self.employee_ids:
You need to loop over self then access employee_ids field value for each record:
Example:
def attendance_validate(self):
for rec in self:
for emp in rec.employee_ids:
You should move the following code outside the for loop
self.write({'state': 'validate', })
Example:
hr_attendance = self.env['hr.attendance']
for rec in self:
for emp in rec.employee_ids:
if emp.is_present == True:
attd_crete_id = hr_attendance .create({'employee_id': emp.employe_id.id,
'check_in': emp.check_in,
'check_out': emp.check_out,
})
rec.write({
'state': 'validate',
})
...
Probably you need to call write state to validate when the attendance_validate method succeed (at the end)
improvement:
The following expression
if emp.is_present == True:
can be simplified to:
if emp.is_present:
You are using two fields is_present and is_absent, you can simply use is_present and when its value is False (not set) the employee is absent.
You need to remove the second if statement, which is useless
elif emp.is_absent == True:
if emp.is_absent == True:
Avoid raising a validation error in the create method because it will break the workflow, instead you can define a constraint on date field:
#api.constrains('date')
def _date_test_unique(self):
for rec in self:
if self.search_count([('date', '=', rec.date)]) > 1:
raise ValidationError(_('Current Date Attendance Already Existed!'))
Update:
The create method should return the newly created record:
#api.model
def create(self, vals):
res = super(CLASS_NAME, self).create(vals)
# Your code
return res
write a for loop before the if statement
#api.onchange('is_present')
def onchange_attendance(self):
for rec in self:
if rec.is_present:
rec.is_absent = False

How to create sample sale order and sale order line in odoo?

I am trying to create a sample order in sales order.In the sample order form, products are sold to customers as complimentary copy(books in my case) without charging any money so I have created a separate sub-menu in sales menu.Here I take only product and quantity as input. Sample order number will be the next number from the sales order(like SO360).So I am fetching sales order number as parent_id in my inherited module.I am not able to create sale order line(data in order lines tab)
class SaleOrder(models.Model):
_inherit = 'sale.order'
# Fields
is_sample = fields.Boolean(string="Sample Order", default=False)
parent_id = fields.Many2one('sale.order', string="Parent Sales Order")
sample_ids = fields.One2many('sale.order', 'parent_id',
string="Sample Orders")
# Methods
#api.model
#api.returns('sale.order')
def create(self, vals):
if vals.get('is_sample', False) and vals.get('name', '/') == '/':
IrSeq = self.env['ir.sequence']
ref = IrSeq.next_by_code('sale.order.sample.ref') or '/'
parent = self.search([('id', '=', vals.get('parent_id'))])
vals['name'] = parent.name + ref
vals['user_id'] = parent.user_id.id
return super(SaleOrder, self).create(vals)
class SampleOrderWizard(models.TransientModel):
_name = 'sale.order.sample.wizard'
_description = 'Sample Sale Order Wizard'
# Field default values
#
def _get_parent(self):
res = False
if self.env.context \
and 'active_id' in list(self.env.context.iterkeys()):
res = self.env.context['active_id']
return res
def _get_new_sale_line(self, orig_sale, orig_sale_line, wizard_line):
"""Internal function to get the fields of the sale order line. Modules
enhancing this one should add their own fields to the return value."""
res = {
'order_id': orig_sale.id,
'product_id': orig_sale_line.product_id.id,
'name': orig_sale_line.name,
'sequence': orig_sale_line.sequence,
'price_unit': orig_sale_line.price_unit,
'product_uom': orig_sale_line.product_uom.id,
'product_uom_qty': wizard_line and wizard_line.qty or 0,
'product_uos_qty': wizard_line and wizard_line.qty or 0,
}
# Simple check for installation of sale_line_code module
if hasattr(orig_sale_line, 'order_line_ref'):
res.update({'order_line_ref': orig_sale_line.order_line_ref})
return res
def _get_order_lines(self, sale):
res = []
for line in sale.order_line:
wizard_line = False
for wzline in self.wizard_lines:
if wzline.product == line.product_id:
wizard_line = wzline
break
if wizard_line:
res.append(
(0, 0, self._get_new_sale_line(sale, line, wizard_line))
)
return res
def _get_wizard_lines(self):
res = []
if self._get_parent():
SaleOrder = self.env['sale.order']
parent = SaleOrder.search([('id', '=', self._get_parent())])
for line in parent.order_line:
res.append((0, 0,
{
'product': line.product_id,
'qty': 1,
}))
return res
# Fields
#
order = fields.Many2one('sale.order', default=_get_parent, readonly=True)
wizard_lines = fields.One2many('sale.order.sample.wizard.line', 'wizard',
default=_get_wizard_lines)
order_date = fields.Datetime(default=fields.Datetime.now())
# Methods
#
#api.one
def create_order(self):
sale_vals = {
'user_id': self.order.user_id.id,
'partner_id': self.order.partner_id.id,
'parent_id': self.order.id,
'date_order': self.order_date,
'client_order_ref': self.order.client_order_ref,
'company_id': self.order.company_id.id,
'is_sample': True,
'order_line': self._get_order_lines(self.order)
}
self.env['sale.order'].create(sale_vals)
return {'type': 'ir.actions.act_window_close'}
class SampleOrderWizardLine(models.TransientModel):
_name = 'sale.order.sample.wizard.line'
_description = 'Sample Order Wizard Line'
wizard = fields.Many2one('sale.order.sample.wizard')
product = fields.Many2one('product.product',
domain=[('sale_ok', '=', True)])
qty = fields.Float(string="Quantity", default=1.0,
digits_compute=dp.get_precision('Product UoS'))

How to override create methode in odoo 10

i want to use same create method in odoo 10 as below means i want to convert below code in odoo 10, below code is working well for odoo 8
def create(self, cr, uid, vals, context=None):
phase_obj = self.pool.get('hr_evaluation.plan.phase')
survey_id = phase_obj.read(cr, uid, vals.get('phase_id'), fields=['survey_id'], context=context)['survey_id'][0]
if vals.get('user_id'):
user_obj = self.pool.get('res.users')
partner_id = user_obj.read(cr, uid, vals.get('user_id'), fields=['partner_id'], context=context)['partner_id'][0]
else:
partner_id = None
user_input_obj = self.pool.get('survey.user_input')
if not vals.get('deadline'):
vals['deadline'] = (datetime.now() + timedelta(days=28)).strftime(DF)
ret = user_input_obj.create(cr, uid, {'survey_id': survey_id,
'deadline': vals.get('deadline'),
'type': 'link',
'partner_id': partner_id}, context=context)
vals['request_id'] = ret
return super(hr_evaluation_interview, self).create(cr, uid, vals, context=context)
i am trying below code:
def create(self, vals):
survey_id = self.env['hr_evaluation.plan.phase'].read(vals.get('phase_id'),fields=['survey_id'])['survey_id'][0]
if vals.get('user_id'):
partner_id = self.env['res.users'].read(vals.get('user_id'), fields=['partner_id'])['partner_id'][0]
else:
partner_id = None
if not vals.get('deadline'):
vals['deadline'] = (datetime.now() + timedelta(days=28)).strftime(DF)
ret = self.env['survey.user_input'].create({'survey_id': survey_id,
'deadline': vals.get('deadline'),
'type': 'link',
'partner_id': partner_id})
vals['request_id'] = ret
return super(hr_evaluation_interview, self).create(vals)
but it is giving me error like TypeError: read() got multiple values for keyword argument 'fields' so please guide me how can i remove this error?
read method accept fields as argument and you give it two arguments.
read([fields])
Reads the requested fields for the records in self, low-level/RPC method. In Python code, prefer browse().
Parameters
fields -- list of field names to return (default is all fields)
Returns
a list of dictionaries mapping field names to their values, with one dictionary per record
Raises
AccessError -- if user has no read rights on some of the given records
Instead of calling read method it's better to call browse() method, you can read Browse() vs read() performance in Odoo 8
Your code should be:
def create(self, vals):
survey_id = self.env['hr_evaluation.plan.phase'].browse(vals.get('phase_id'))
if vals.get('user_id'):
partner_id = self.env['res.users'].browse(vals.get('user_id'))
else:
partner_id = None
if not vals.get('deadline'):
vals['deadline'] = (datetime.now() + timedelta(days=28)).strftime(DF)
ret = self.env['survey.user_input'].create({'survey_id': survey_id.id,
'deadline': vals.get('deadline'),
'type': 'link',
'partner_id': partner_id.id})
vals['request_id'] = ret.id
return super(hr_evaluation_interview, self).create(vals)

Multiple creations on Odoo/Openerp res.partner table fail when one by one succeed

Here is what I am trying to do, I have a CSV file that has some records that I want to import on my installation. The following code works when I put a return None statement on the end of the loop. (Which you will find commented out
Upon the click of a button this method will be executed in order to loop through all the rows on the CSV and depending on the conditions create a new res.partner record.
(this has been implemented via XML-RPC calls and it worked flawlessly.)
The problem is this: When I stop the execution after the import of one CSV row, everything works (the record on res.partner is created), when I leave it running with the loop no records are created on the table res.partner (I get no errors, no exceptions whatsoever. I even get the newly created record's id upon the invocation of res_partner_obj.create() ).
Note: You will find lots of irrelevant code to my problem (which is why the records on res.partner are not created). I just put it there for the sake of completeness)
def gms_import_test(self, cr, uid, vals, context=None, check=True):
start_time = time.time()
res_partner_obj = self.pool.get('res.partner')
sales_teams_obj = self.pool.get('crm.case.section')
res_partner_title_obj = self.pool.get('res.partner.title')
customer_kunden_obj = self.pool.get('customer.kundengruppe')
res_country_obj = self.pool.get('res.country')
account_account_obj = self.pool.get('account.account')
crm_phonecall_obj = self.pool.get('crm.phonecall')
account_account_type_obj = self.pool.get('account.account.type')
# sys.path[0] == module's path + /addons/gmsimport/+ file's name
with open(sys.path[0] + '/addons/gmsimport/' + '21.9.2015.try8.csv') as csv_file: # TODO THESE MUST CHANGE UPON DEPLOYMENT TO DIFFERENT MACHINES
csv_reader = csv.reader(csv_file, delimiter='~', quotechar='^')
# Get the teams
sales_team_direct_sales_ID = sales_teams_obj.search(cr, uid, [('name', '=', 'Direct Sales')])
sales_team_0_ID = sales_teams_obj.search(cr, uid, [('name', '=', '0')])
sales_team_1_ID = sales_teams_obj.search(cr, uid, [('name', '=', '1')])
sales_team_2_ID = sales_teams_obj.search(cr, uid, [('name', '=', '2')])
sales_team_3_ID = sales_teams_obj.search(cr, uid, [('name', '=', '3')])
sales_team_4_ID = sales_teams_obj.search(cr, uid, [('name', '=', '4')])
sales_team_5_ID = sales_teams_obj.search(cr, uid, [('name', '=', '5')])
sales_team_6_ID = sales_teams_obj.search(cr, uid, [('name', '=', '6')])
sales_team_7_ID = sales_teams_obj.search(cr, uid, [('name', '=', '7')])
sales_team_8_ID = sales_teams_obj.search(cr, uid, [('name', '=', '8')])
sales_team_9_ID = sales_teams_obj.search(cr, uid, [('name', '=', '9')])
# Search for the titles, create them if they do not exist
damen_und_herren_title_ID = res_partner_title_obj.search(cr, uid, [('name', '=', 'Sehr geehrte Damen und Herren')])
if not damen_und_herren_title_ID:
damen_und_herren_title_ID = res_partner_title_obj.create(cr, uid, {'name':'Sehr geehrte Damen und Herren'})
if type(damen_und_herren_title_ID) is list:
damen_und_herren_title_ID = damen_und_herren_title_ID[0]
frau_title_ID = res_partner_title_obj.search(cr, uid, [('name', '=', 'Sehr geehrte Frau')])
if not frau_title_ID:
frau_title_ID = res_partner_title_obj.create(cr, uid, {'name':'Sehr geehrte Frau'})
if type(frau_title_ID) is list:
frau_title_ID = frau_title_ID[0]
herr_title_ID = res_partner_title_obj.search(cr, uid, [('name', '=', 'Sehr geehrter Herr')])
if not herr_title_ID:
herr_title_ID = res_partner_title_obj.create(cr, uid, {'name':'Sehr geehrter Herr'})
if type(herr_title_ID) is list:
herr_title_ID = herr_title_ID[0]
account_type_id = account_account_type_obj.search(cr, uid, [('name', '=', 'Receivable')])
# Checking to see whether there exists the "1200 - Forderungen aus Lieferungen und Leistungen account"
forderungen_account = account_account_obj.search(cr, uid, [('code', '=', 1200)])
if type(forderungen_account) is list and len(forderungen_account) > 0:
forderungen_account = forderungen_account[0]
account_payable_ID = account_account_obj.search(cr, uid, [('code', '=', 'Kunden - Diverse1')])
if type(account_payable_ID) is list:
account_payable_ID = account_payable_ID[0]
next(csv_reader, None) # To skip header row.
row_counter = 2
empty_name_counter = 0
for row in csv_reader:
print 'PROCESS IN ROW: ' + str(row_counter)
final_customer_name = None
if len(str(row[15]).strip()) > 0:
# If Firma is not empty, customer's name == Firma + Zusatz
final_customer_name = row[15] + ' ' + row[64]
else:
# If Firma is empty, customer's name == Vorname + Name
final_customer_name = row[63] + ' ' + row[45]
if final_customer_name:
empty_name_counter += 1
logging.info("Customer name is " + str(final_customer_name))
# search for the customer's existance, if exists do not add her
customer_id = res_partner_obj.search(cr, uid, [('name', '=', final_customer_name)])
print 'Searching with customer name ' + final_customer_name
if not customer_id:
# Customer does not exist, only then make the calls
# Fields with relations that must be treated in a special way
# x_kundengruppe, country_id, name
print 'customer.kundengruppe ' + str(row[6])
x_kundengruppe_id = customer_kunden_obj.search(cr, uid, [('name', '=', row[6].decode('utf8'))])
if not x_kundengruppe_id:
# kundergruppe does not exist (create a record on the model customer.kundengruppe and store its id)
print 'Creating kundengruppe'
x_kundengruppe_id = customer_kunden_obj.create(cr, uid, {'name':row[6]})
country_id = []
if str(row[27]).strip():
if str(row[27]) == 'Great Britain':
country_id = res_country_obj.search(cr, uid, [('name', '=', 'United Kingdom')])
else:
country_id = res_country_obj.search(cr, uid, [('name', '=', row[27])])
mittarbeitergrupe = None
if row[16] == '0 bis 4':
mittarbeitergrupe = '0_4'
elif row[16] == '5 bis 9':
mittarbeitergrupe = '5_9'
elif row[16] == '10 bis 19':
mittarbeitergrupe = '10_19'
elif row[16] == '20 bis 34':
mittarbeitergrupe = '20_34'
elif row[16] == '35 bis 49':
mittarbeitergrupe = '35_49'
elif row[16] == '50 bis 99':
mittarbeitergrupe = '50_99'
elif row[16] == 'über 100':
mittarbeitergrupe = 'uber_100'
final_customer_number_list = []
final_customer_number = None
print row[10]
if len(row[10]) < 8:
# Get row[10] length. Subtract it from 8. That's how many zeros must be put. Create a new string with zeros in front and number postfixed
zeros = 8 - len(row[10])
# final_customer_number_list.append('\'')
for y in range(0, zeros):
final_customer_number_list.append(str(0))
final_customer_number_list.append(str(row[10]))
# final_customer_number_list.append('\'')
final_customer_number = ''.join(final_customer_number_list)
print 'Customer\'s number length < 8. Prefixing ' + str(zeros) + ' zeros'
print 'final x_customer_number: ' + str(final_customer_number)
else:
final_customer_number = str(row[10])
# Make the country_id from an array to a single int variable
if len(country_id) > 0:
print 'SETTING COUNTRY ID TO ' + str(country_id)
country_id = country_id[0]
if type(x_kundengruppe_id) is list and len(x_kundengruppe_id) > 0:
x_kundengruppe_id = x_kundengruppe_id[0]
comment_section = self.assemble_internal_log(row)
final_title = self.assemble_customer_title(row, damen_und_herren_title_ID, frau_title_ID, herr_title_ID)
# Check x_mitarbeiter
if len(row[2].strip()) == 0:
row[2] = 0
else:
row[2] = int(row[2])
fields_to_be_inserted = { 'x_kundengruppe':x_kundengruppe_id,
'x_customer_number':final_customer_number, # (customer number cannot be less than 8 digits)
'vat':row[12],
'email':row[14],
'name':final_customer_name,
'x_mittarbeitergruppe':mittarbeitergrupe,
'title':final_title,
'x_a_kunde':row[23],
'website':row[24],
'country_id':country_id,
'mobile':filter(lambda x: x.isdigit(), row[44]),
'city':row[46],
'zip':row[49],
'function':str(row[50]),
'street':row[57] + str(row[21]), # street and House No
'fax':filter(lambda x: x.isdigit(), row[59]),
'phone':filter(lambda x: x.isdigit(), row[60]),
'comment':comment_section,
'x_mitarbeiter':row[2],
'property_account_payable':account_payable_ID,
}
log_entries = []
# column_index_list = [67, 68, 76, 77, 85, 86, 94, 95, 103, 104, 112, 113, 121, 122, 130, 131, 139, 140, 148, 149, 157, 158, 166, 167, 175, 176, 184, 185, 193, 194, 202, 203, 211, 212, 220, 221, 229, 230, 238, 239, 247, 248]
column_index_list = [67, 76, 85, 94, 103, 112, 121, 130, 139, 148, 157, 166, 175, 184, 193, 202, 211, 220, 229, 238, 247]
# search through the CSV to find those fields that contain (log note/date) and put them in internal log
for x in column_index_list:
if len(row[x].strip()) > 0:
print 'Log entry found, adding to the list'
log_entries.append(row[x + 1] + '||||' + row[x])
if customer_id:
# Customer exists, do not add her
print 'Customer ' + final_customer_name + ' exists. We do not add this one.'
logging.info('Customer ' + final_customer_name + ' exists. We do not add this one.')
else:
try:
logging.info('Creating customer ' + str(final_customer_name) + ', ' + str(row[15]))
created_customer_id = res_partner_obj.create(cr, uid, fields_to_be_inserted)
print 'CREATED CUSTOMER: ' + str(final_customer_name) + ' ID: ' + str(created_customer_id)
sales_team_id = None
# If PLZ field is not empty and is a 5 digit number
if row[49] and str(row[49]).isdigit() and len(str(row[49])) == 5:
# Check the first digit and assign to it a Sales Team
if int(str(row[49])[0]) == 1:
sales_team_id = sales_team_1_ID
elif int(str(row[49])[0]) == 2:
sales_team_id = sales_team_2_ID
elif int(str(row[49])[0]) == 3:
sales_team_id = sales_team_3_ID
elif int(str(row[49])[0]) == 4:
sales_team_id = sales_team_4_ID
elif int(str(row[49])[0]) == 5:
sales_team_id = sales_team_5_ID
elif int(str(row[49])[0]) == 6:
sales_team_id = sales_team_6_ID
elif int(str(row[49])[0]) == 7:
sales_team_id = sales_team_7_ID
elif int(str(row[49])[0]) == 8:
sales_team_id = sales_team_8_ID
elif int(str(row[49])[0]) == 9:
sales_team_id = sales_team_9_ID
# If the PLZ field is not empty and is a 4 digit number
elif row[49] and str(row[49]).isdigit() and len(str(row[49])) == 4: # int(row[49]) >= 0 and int(row[49]) <= 9999:
sales_team_id = sales_team_0_ID
# Everything else goes to the Direct Sales team
else:
sales_team_id = sales_team_direct_sales_ID
if len(sales_team_id) > 0:
print 'SECTION ID: ' + str(sales_team_id)
res_partner_obj.write(cr, uid, created_customer_id, {'section_id':str(sales_team_id[0])})
# personal account for each customer
# Check if account exists for certain customer
account_id = account_account_obj.search(cr, uid, [('name', '=', final_customer_name)])
if not account_id:
print 'Creating and linking new account for customer ' + final_customer_name + ' CODE: ' + str(row[10])
# Creating account (parent_id can be empty. If so, do not change the parent_id field; let it be)
account_id = account_account_obj.create(cr, uid, {'code': row[10],
'name': final_customer_name,
'type':'receivable',
'user_type': account_type_id[0],
'parent_id': forderungen_account
})
# In any case assign the account to the customer
if type(account_id) is list:
account_id = account_id[0]
print 'ACCOUNT ID TO LINK' + str(account_id)
res_partner_obj.write(cr, uid, created_customer_id, {'property_account_receivable':account_id})
except Exception, e:
#pass
print '===> ERROR ' + str(e) # If error on account creation, no problem keep going
for log_entry in log_entries:
log = log_entry.split('||||', 2)
crm_phonecall_obj.create(cr, uid, {'date':log[0], 'name':log[1], 'state':'done', 'partner_id':created_customer_id})
if time.time() - start_time > 500:
print '500 secs passed'
return None
row_counter += 1
#return None