I create sequence in customer module sale, and _inherit to res.partner but I get fill 'New' in my sequence field when I create new customer
group_id = fields.Many2one(
'group.customer',
string="Group"
)
#api.model
def create(self, value):
if self.group_id.name == 'Dealer':
if value.get('code_customer', _('New')) == _('New'):
value['code_customer'] = self.env['ir.sequence'].next_by_code('code.customer.dealer') or _('New')
result = super(res_partner, self).create(value)
return result
That is a wrong way to inherit create function. Here is the correct one:
#api.model
def create(self, value):
group_id = value.get('group_id')
if group_id:
group = self.env['group.customer'].browse(group_id)
if group.name=='Dealer' and value.get('code_customer', _('New')) == _('New'):
value['code_customer'] = self.env['ir.sequence'].next_by_code('code.customer.dealer') or _('New')
result = super(res_partner, self).create(value)
return result
Related
I create data from the account.reconciliation.act model into the direct.statistics model
Then I want to change some data in account.reconciliation.act. and it does not change in the direct.statistics model. I have written a write method with which I would like to update the data in the direct.statistic model.
But it doesn't work. What did I do wrong?
I get the error TypeError: write() takes 2 positional arguments but 3 were given
1.py
class AccountReconciliationAct(models.Model):
_name = "account.reconciliation.act"
direct_statistics_id = fields.Many2one(comodel_name="direct.statistics", string="Direct Statistics")
#api.model
def create(self, values):
....
else:
self.env["direct.statistics"].create({
"direct_advertiser_id": record_id.partner_id.id,
"direct_payment_net_id": record_id.payment_net_id.id,
"direct_currency_id": record_id.currency_id.id,
"direct_last_act_date": record_id.reconciliation_act_date,
"direct_total_amount": record_id.amount_total,
"direct_department_ids": record_id.reconciliation_act_line_ids.department_id
})
return record_id
#api.model
def write(self, values):
res = super().write(values)
self.env["direct.statistics"].update({
"direct_advertiser_id": self.partner_id.id,
"direct_payment_net_id": self.payment_net_id.id,
"direct_currency_id": values.get('currency_id.id'),
"direct_last_act_date": values.get('reconciliation_act_date'),
"direct_total_amount": values.get('amount_total'),
"direct_department_ids": values.get('reconciliation_act_line_ids.department_id'),
})
return res
2.py
class DirectStatistics(models.Model):
_name = "direct.statistics"
_description = "Direct statistics"
_rec_name = "direct_advertiser_id"
direct_advertiser_id = fields.Many2one(comodel_name="res.partner", string="Advertiser")
direct_manager_id = fields.Many2one(related="direct_advertiser_id.manager_id", string="Manager")
direct_payment_net_id = fields.Many2one(related="direct_advertiser_id.payment_net_id", string="Net")
direct_currency_id = fields.Many2one(comodel_name="res.currency", string="Currency")
direct_conversion_ids = fields.Many2many(comodel_name="affise.conversion", string="Conversions")
direct_last_act_date = fields.Date(string="Last Act Date", compute="_compute_direct_last_act_date", store=True)
direct_first_conversion_date = fields.Date(
string="First Conversion Date", compute="_compute_direct_first_conversion_date", store=True
)
direct_department_ids = fields.Many2many(
comodel_name="affise.department", compute="_compute_direct_department_ids", string="Department"
)
direct_reconciliation_act_ids = fields.Many2many(
comodel_name="account.reconciliation.act", string="Created Acts", domain=[("state", "!=", "cancel")]
)
direct_total_amount = fields.Monetary(
currency_field="direct_currency_id", string="Total Acts")
class AccountReconciliationAct(models.Model):
_name = "account.reconciliation.act"
direct_statistics_id = fields.Many2one(comodel_name="direct.statistics", string="Direct Statistics")
#api.model
def create(self, values):
record_id = super(AccountReconciliationAct, self).create(values)
....
else:
record_id.direct_statistics_id = self.env["direct.statistics"].create({
"direct_advertiser_id": record_id.partner_id.id,
"direct_payment_net_id": record_id.payment_net_id.id,
"direct_currency_id": record_id.currency_id.id,
"direct_last_act_date": record_id.reconciliation_act_date,
"direct_total_amount": record_id.amount_total,
"direct_department_ids": record_id.reconciliation_act_line_ids.department_id
})
return record_id
def write(self, values):
res = super(AccountReconciliationAct, self).write(values)
self.direct_statistics_id.update({
"direct_advertiser_id": self.partner_id.id,
"direct_payment_net_id": self.payment_net_id.id,
"direct_currency_id": values.get('currency_id.id'),
"direct_last_act_date": values.get('reconciliation_act_date'),
"direct_total_amount": values.get('amount_total'),
"direct_department_ids": values.get('reconciliation_act_line_ids.department_id'),
})
return res
The first thing you need to do is write the created object to direct_statistics_id field. This is done so that you can update the value in write method. Also don't need to call #api.model for write methods.
I have two models in my odoo project. Employee and equipment, as shown bellow.
Equipment/model.py
from openerp import models, fields, api
import datetime
class equipment(models.Model):
_name = 'equipment.equipment'
name = fields.Char(string='Name', )
date_of_purchase = fields.Date(string='Date Of Purchase', default=fields.Date.today(), )
write_off_days = fields.Integer(string="Days To Write-off", required=True, )
write_off_date = fields.Date(string="Write-off Date", compute="_get_write_off_date", )
price = fields.Float(string="Price '$'", required=True, )
description = fields.Char(string="Description", required=False, )
employee_id = fields.Char(string="Owner", compute="_get_owner", )
#api.one
#api.depends('employee_id')
def _get_owner(self):
//result = self.env.['res.equipment_table'].
//get id from relation database <-------------
#api.one
#api.depends('write_off_days', 'date_of_purchase')
def _get_write_off_date(self):
date = datetime.datetime.strptime(self.date_of_purchase, "%Y-%m-%d")
self.write_off_date = date + datetime.timedelta(days=self.write_off_days)
employee/model.py
from openerp import models, fields, api
class employee(models.Model):
_name = 'employee.employee'
name = fields.Char(string='First Name')
last_name = fields.Char(string='Last Name')
birth_date = fields.Date(string='Birth Date', default=fields.Date.today(), )
equipment_ids = fields.Many2many(string="Equipment", comodel_name="equipment.equipment", relation="equipment_table", )
total_equipment_price = fields.Float(string="Total Equipment Price '$'", compute="_get_total_equipment_price", )
#api.one
#api.depends('equipment_ids')
def _get_total_equipment_price(self):
total = 0
for equipment in self.equipment_ids:
total += equipment.price
self.total_equipment_price = total
I have many2many field, which holds all equipment that employee owns. I need to update the equipment owner every time the field is changed. The reason for this is.. when a user adds new equipment to the employee, there should be shown only unowned equipment. That is why I need to check and update the owner.
I already made a domain to check if equipment already has an owner, which will be shown below. Just need to update that employee_id field somehow.
<notebook>
<page string="Equipment">
<group>
<field name="equipment_ids" domain="[('employee_id', '=', False)]"/>
</group>
</page>
</notebook>
Change the type of employee_id to Many2one:
employee_id = fields.Many2one('employee.employee', string="Owner")
Override create and write methods to set employee_id each time new equipment is added to the list:
class Employee(models.Model):
_name = 'employee.employee'
#api.model
def create(self, values):
res = super(Employee, self).create(values)
if res.equipment_ids:
res.equipment_ids.write({'employee_id': res.id})
return res
#api.multi
def write(self, values):
res = super(Employee, self).write(values)
for r in self:
equipment_ids = r.equipment_ids.filtered(lambda s: not s.employee_id)
if equipment_ids:
equipment_ids.write({'employee_id': r.id})
return res
Because an equipment can set to one owner, I suggest you to change the type of equipment_ids to One2many to be able to set a list of equipments by employee and the employee_id field value will be set automatically for you when you add equipment to the list.
If you change the value of employee_id the equipment will be automatically visible in the list of equipments of the new employee.
equipment_ids = fields.One2many("equipment.equipment", 'employee_id', string="Equipments")
Reset owner
#api.multi
def write(self, values):
removed_ids = set()
old_ids = {r.id: r.equipment_ids.ids for r in self}
res = super(Employee, self).write(values)
for r in self:
equipment_ids = r.equipment_ids.filtered(lambda s: not s.employee_id)
if equipment_ids:
equipment_ids.write({'employee_id': r.id})
removed_ids |= set(old_ids[r.id]) - set(r.equipment_ids.ids)
self.equipment_ids.browse(removed_ids).write({'employee_id': False})
return res
I know my object type is not matching to compare. I tried on #api.onchange but it says:
NullObject is not iterable for selection fields.
Code:
from odoo import models,api,fields
class semester(models.Model):
_name = 'module2_semester'
_description = 'Semester_Info'
_rec_name = 'sem_id'
sub = fields.Many2many('module2_subject')
cou_id = fields.Many2one('module2_course',"Course Name",required=True)
sem_id = fields.Char("Semester ID")
sem_name = fields.Selection(selection='_getSem_value',string="Semester")
reg_no = fields.Integer("Registration Number",size=20)
#api.model
def _getSem_value(self):
print("hello")
print(self.cou_id)
if self.cou_id=='BTECH':
return [('1','1'),
('2','2'),
('3','3'),
('4','4'),
('5','5'),
('6','6'),
('7','7'),
('8','8')]
if self.cou_id=='MCA':
return [('1','1'),
('2','2'),
('3','3'),
('4','4'),
('5','5'),
('6','6')]
if self.cou_id=='MTECH':
return [('1','1'),
('2','2'),
('3','3'),
('4','4')]
You can change the Semester field type to many2one and set the attribute widget to selection in the view definition.
When the value of cou_id changes you have just to filter the records shown in the selection field by returning a custom domain.
class Semester(models.Model):
_name = 'semester'
_description = 'Semester'
name = fields.Integer()
class semester(models.Model):
_name = 'module2_semester'
_description = 'Semester_Info'
_rec_name = 'sem_id'
sub = fields.Many2many('module2_subject')
cou_id = fields.Many2one('module2_course',"Course Name",required=True)
sem_id = fields.Char("Semester ID")
# sem_name = fields.Selection(selection='_getSem_value',string="Semester")
reg_no = fields.Integer("Registration Number",size=20)
sem_name = fields.Many2one('semester', string="Semester")
#api.onchange('cou_id')
def _course_changed(self):
self.sem_name = False
if self.cou_id:
# Initialize `semesters` in case `cou_id.name` is not listed below
semesters = 0
if self.cou_id.name == 'BTECH':
semesters = 8
if self.cou_id.name == 'MCA':
semesters = 6
if self.cou_id.name == 'MTECH':
semesters = 4
sem_ids = self.env['semester'].search([('name', '<=', semesters )])
return {'domain': {'sem_name': [('id', 'in', sem_ids.ids)]}}
In the view definition:
<field name="sem_name" widget="selection"/>
I want to check a boolean field, from a parent class, into a child (lines) class.
class bsi_print_order(models.Model):
_name = 'bsi.print.order'
#api.model
def create(self, vals):
if vals.get('name', 'New') == 'New':
vals['name'] = self.env['ir.sequence'].next_by_code('bsi.print.order') or '/'
return super(bsi_print_order, self).create(vals)
name = fields.Char('Reference', required=True, index=True, copy=False, readonly='True', default='New')
date = fields.Date(string="Print Date",default=fields.Datetime.now)
production_orders = fields.Many2one('bsi.production.order', ondelete='cascade', string="Production Order")
due_date = fields.Date(string="Due Date")
journal_entry = fields.Many2one('account.move', string="Journal Entry")
stock_picking_id = fields.Many2one('stock.picking', string="Stock Picking")
order_picking = fields.One2many('bsi.print.order.lines', 'print_order', string="Order lines")
book_block = fields.Boolean(string="Book Block", default=True)
binding = fields.Boolean(string="Binding")
edging = fields.Boolean(string="Edging")
class bsi_print_order_lines(models.Model):
_name = 'bsi.print.order.lines'
print_order = fields.Many2one('bsi.print.order', string="Print Order")
isbn = fields.Many2one('product.product', string="ISBN", domain="[('is_isbn', '=', True)]")
qty = fields.Integer(string="Quantity")
consumed_qty = fields.Integer(string="Quantity consumed")
remaining_qty = fields.Float(string="Remaining quantity") #, compute="_remaining_func"
is_book_block = fields.Boolean(string="Is Book Block Done")
is_binding = fields.Boolean(string="Is Binding Done")
is_edging = fields.Boolean(string="Is Edging Done")
isbns = fields.Many2one('worksheets.isbns', string="Worksheet ISBNS")
So, when book_block button is checked, is_book_block should be automatically checked too, same with binding and edging, they should check is_binding and is_edging respectively.
These are the methods I have:
#api.depends('book_block', 'order_picking', 'order_picking.is_book_block')
def _bool_book_block(self):
if self.book_block == True:
order_picking.is_book_block = True
else:
order_picking.is_book_block = False
#api.depends('binding', 'order_picking', 'order_picking.is_binding')
def _bool_binding(self):
if self.binding == True:
order_picking.is_binding = True
else:
order_picking.is_binding = False
#api.onchange('edging', 'order_picking', 'order_picking.is_edging')
def _bool_edging(self):
if self.edging == True:
order_picking.is_edging == True
else:
order_picking.is_edging == False
But it doesn't work, I do check edging for example, and even save the document, but no changes on the boolean fields in lines.
Any ideas?
When you use depends the field must have a compute attribute :
some_feild = fiels.SomeType(......., compute='method_name')
#api.depends('some_field_2', ...)
def method_name(self):
# and here the function will be computed.
If your field are 100% computed field, best thing in odoo that you
can listen for changing in the parent class to compute the child field:
class bsi_print_order(models.Model):
_name = 'bsi.print.order'
....
class bsi_print_order_lines(models.Model):
_name = 'bsi.print.order.lines'
is_book_block = fields.Boolean(string="Is Book Block Done", compute="compute_book_block")
#api.depends('print_order.book_block')
def compute_book_block(self):
# in depends it's always a good this to loop
# or use api.one with depends
for rec in self:
if rec.print_order:
self.is_book_block = self.print_order.book_block
But this is Ok only if this field is always a compute field, i mean the user will never
change it's value from the UI.
If your field is not computed and the user can change the value if he want than you need to use
onchange in the parent class.
class bsi_print_order(models.Model):
_name = 'bsi.print.order'
....
#api.onchange('book_block '):
def onchange_book_block(self):
# in onchange no need for loop
# because self should always have only one recod
for line in self.order_picking:
line.is_book_block = self.book_block
I want to create recordset with product in my custom class from sale order after calling an event. I will create a record in sale.order and like creating invoice, I will create record in my custom module.
What I have done is:
In my custom class:
class LoadingSlip(models.Model):
_name = 'loading.slip'
_description = 'loading information'
partner_id = fields.Char("Customer Name")
order_date = fields.Date("Order Date")
expiration_date = fields.Date("Expiration Date")
# order_line = fields.One2many('sale.order.line', 'order_id', string="Order Lines")
product_line = fields.One2many('loading.product.line', 'loading_product', string="Loading Products")
class LoadingProduct(models.Model):
_name = 'loading.product.line'
_description = "Loading Product Informations"
products_id = fields.Many2one('product.product', string='Product',
ondelete='restrict', index=True)
quantity = fields.Float(string='Quantity', default=1)
loading_product = fields.Many2one('loading.slip', string="Loading Reference", ondelete='cascade', index='True')
In sale.order
class sale_func(models.Model):
_inherit = 'sale.order'
#api.multi
def _prepare_slip(self):
test.set_trace()
self.ensure_one()
slip = {
'partner_id': self.partner_id.name,
'order_date': self.date_order,
'expiration_date': self.validity_date,
}
return slip
#api.multi
def action_slip_create(self, grouped=False, final=False):
test.set_trace() # debug point
pprint(self)
inv_obj = self.env['loading.slip']
precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
slips={}
pprint(slips)
slipReferences={}
test.set_trace()
for order in self:
group_key = order.id
test.set_trace()
for line in order.order_line:
if group_key not in slips:
inv_data = order._prepare_slip()
loadingslip = inv_obj.create(inv_data)
slipReferences[loadingslip] = order
slips[group_key] = loadingslip
if line.product_uom_qty > 0:
line.slip_line_create(slips[group_key].id)
if not slips:
raise UserError(_('There is no loading slip line.'))
#api.multi
def create_slip(self):
test.set_trace()
pprint(self)
sale_orders = self.env['sale.order'].browse(self._context.get('active_ids', []))
self.action_slip_create(sale_orders)
In sale.order.line
class sales_order(models.Model):
_inherit="sale.order.line"
#api.multi
def _prepare_slip_line(self):
test.set_trace()
self.ensure_one()
res={}
pprint(res)
res={
'products_id': self.product_id.id or False,
'quantity': self.product_uom_qty
}
pprint(res)
#api.multi
def slip_line_create(self, loading_product):
test.set_trace()
prdct_order = self.env['loading.product.line']
for line in self:
vals = line._prepare_slip_line()
prdct_order.create(vals)
My error is:
> /home/diwap/odoo-dev/custom-addons/sales_ext_agni/models/models.py(196)slip_line_create()
195 vals = line._prepare_slip_line()
--> 196 prdct_order.create(vals)
197
ipdb> n
TypeError: "argument of type 'NoneType' is not iterable"
I have tried update and write method instead of create in line 196 but I could not get any result it's just come up with an empty field and also no error. However when I try the real thing and i.e. write() I get this error. Is there any wrong somewhere in my code or its just an horrible thing I am doing.