I have 2 models "Inventory" and "Scrap". There is a button. I want to, if i click the button the data move to scrap model. It is okay i did that. But except one variable, "Many2one".
So I'm getting this error, when i click the button: "psycopg2.ProgrammingError: can't adapt type 'ware.houses' odoo".
This is my Inventory Module.
class InventoryMenu(models.Model):
_name = "inventory.menu"
_description = "Inventory Menü"
ref_code = fields.Char(string="Referans Numarası: ", required=True, tracking=True, default="000000")
product_name = fields.Char(string="Ürün Adı: ", required=True, tracking=True,)
product_description = fields.Char(string="Ürün Tanımı: ", required=True, 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,)
unit_price = fields.Float(string="Birim Fiyat: ", compute="_unitPriceCalcuteFunc")
warehouse_id = fields.Many2one('ware.houses', string='Depo Adı: ')
#api.depends('quantity', 'price')
def _unitPriceCalcuteFunc(self):
for record in self:
record.unit_price = record.price * record.quantity
def action_delete(self):
vals = {
'ref_code': self.ref_code,
'product_name': self.product_name,
'product_description': self.product_description,
'teslim_alan': self.teslim_alan,
'teslim_eden': self.teslim_eden,
'quantity': self.quantity,
'price': self.price,
'unit_price': self.unit_price,
'warehouse_id': self.warehouse_id
}
self.env['scrap'].create(vals)
return super(InventoryMenu, self).unlink()
This is my Scrap module:
class Scrap(models.Model):
_name = "scrap"
_description = "Scrap"
ref_code = fields.Char(string="Referans Numarası: ", required=True, tracking=True, default="000000")
product_name = fields.Char(string="Ürün Adı: ", required=True, tracking=True, )
product_description = fields.Char(string="Ürün Tanımı: ", required=True, 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, )
unit_price = fields.Float(string="Birim Fiyat: ", compute="_unitPriceCalcuteFunc")
warehouse_id = fields.Many2one('ware.houses', string='Depo Adı: ')
#api.depends('quantity', 'price')
def _unitPriceCalcuteFunc(self):
for record in self:
record.unit_price = record.price * record.quantity
def action_getback(self):
vals = {
'ref_code': self.ref_code,
'product_name': self.product_name,
'product_description': self.product_description,
'teslim_alan': self.teslim_alan,
'teslim_eden': self.teslim_eden,
'quantity': self.quantity,
'price': self.price,
'unit_price': self.unit_price,
'warehouse_id': self.warehouse_id
}
self.env['inventory.menu'].create(vals)
return super(Scrap, self).unlink()
Here is the solution for above code:
'warehouse_id': self.warehouse_id
Please change this line to:
'warehouse_id': self.warehouse_id.id
While creating your vals in action_delete and action_getback methods.
Root Cause: When you pass dictionary of values which you want to create in your model, make sure that every field have correct value.
For EX: If field is Many2one than you need to pass the record_id (type=int), because odoo will directly browse the id to the related model and place the record to that field.
Related
how to make field become auto fill when i create new record from bank_account.py field to account_account.py field.
bank_account.py
class BankAccounAccount(models.Model):
_name = 'bank.account.account'
_description = "Bank Account Account"
_rec_name = 'acc_number'
acc_number = fields.Char(string="Account Number", required=True)
bank_id = fields.Many2one('res.bank', string="Bank")
bank_bic = fields.Char(string="Bank Identifier Code")
company_id = fields.Many2one('res.company', string="Company", default=lambda self: self.env.user.company_id.id)
branch_id = fields.Many2one('res.branch', string="Branch")
account_account.py
class AccountJournal(models.Model):
_inherit = "account.journal"
name = fields.Char(string='Journal Name', required=True,
tracking=True)
company_partner_id = fields.Many2one('res.partner', related='company_id.partner_id', string='Account Holder', readonly=True, store=False)
bank_account_id = fields.Many2one('res.partner.bank',
string="Bank Account",
ondelete='restrict', copy=False,
check_company=True,
domain="[('partner_id','=', company_partner_id), '|', ('company_id', '=', False), ('company_id', '=', company_id)]",
tracking=True)
company_id = fields.Many2one('res.company', string='Company', required=True, readonly=True, index=True, default=lambda self: self.env.company,
help="Company related to this journal",
tracking=True)
bank_statements_source = fields.Selection(selection=_get_bank_statements_available_sources, string='Bank Feeds', default='undefined', help="Defines how the bank statements will be registered",
tracking=True)``
bank_acc_number = fields.Char(related='bank_account_id.acc_number', readonly=False,
tracking=True)
bank_id = fields.Many2one('res.bank', related='bank_account_id.bank_id', readonly=False,
tracking=True)
`
when created new account 'acc_number' record auto filled into name field and company_id to company id
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)
I have inherited account.move model and added job_card_id field(many2one) in it, as shown as below :
Image
Below given is Image of Selected Job Card :
Image
Below given is code of my model and I also tried creating function below fields :
class JobCard(models.Model):
_name = "job.card"
_inherit = ['mail.thread', 'mail.activity.mixin']
_description = "Job Card Master"
_rec_name = 'job_card_number'
job_card_number = fields.Char(string='Job Card No.', readonly=True)
customer_id = fields.Many2one('res.partner', string="Customer Name", tracking=True)
vehicle_id = fields.Many2one('res.partner.line', string="Vehicle", tracking=True,
domain="[('x_customer_id','=',customer_id)]")
date_time_of_invoice = fields.Datetime(string='Date & Time of Invoice', tracking=True, default=fields.Datetime.now)
start_date_time = fields.Datetime(string='Start Date & Time', tracking=True)
end_date_time = fields.Datetime(string='End Date & Time', tracking=True)
priority = fields.Selection([
('0', 'Normal'),
('1', 'Low'),
('2', 'High'),
('3', 'Very High')], string="Priority") # priority widget
state = fields.Selection([
('draft', 'Draft'),
('in_progress', 'In Progress'),
('done', 'Done'),
('cancel', 'Cancelled')], string="Status", default='draft', required=True) # status bar
active = fields.Boolean(string="Active", default=True, tracking=True)
x_product_ids = fields.Many2many('job.card.line', 'product_id', string="Job Card Details")
x_quantity_ids = fields.One2many('job.card.line', 'quantity', string="Job Card Details")
x_price_ids = fields.One2many('job.card.line', 'price', string="Job Card Details")
x_total_ids = fields.One2many('job.card.line', 'total', string="Job Card Details")
x_employee_ids = fields.One2many('job.card.line', 'employee_id', string="Job Card Details")
x_job_card_ids = fields.One2many('job.card.line', 'job_card_id', string="Job Card Details")
job_card_count = fields.Integer(compute='compute_job_card_count', string='Job Card Count')
def get_invoice_line_vals(self):
vals_list = []
for job_card_line in self.x_product_ids:
vals_list.append({
' price_unit': job_card_line.price_unit,
'quantity': job_card_line.quantity
})
return vals_list
Below given is code of inherited model and also added onchange function :
class CustomInvoice(models.Model):
_inherit = "account.move"
job_card_id = fields.Many2one('job.card', string="Job Card", domain="[('customer_id','=',partner_id)]",
tracking=True)
#api.onchange('job_card_id')
def _onchange_job_card_id(self):
# creates your invoice lines vals according to your values
invoice_lines_vals = self.job_card_id.get_invoice_line_vals()
self.update({'invoice_line_ids': [(5, 0)] + [(0, 0, vals) for vals in invoice_lines_vals]})
Below given is code of my job card line :
class JobCardLine(models.Model):
_name = "job.card.line"
job_card_id = fields.Many2one('job.card', string="Job Card Id", tracking=True)
product_id = fields.Many2one('product.template', string="Product", tracking=True)
quantity = fields.Integer(string="Quantity", tracking=True)
# price = fields.Char(string="Price")
price = fields.Float(string="Price")
total = fields.Integer(string='Total', compute='_compute_total', tracking=True,
help="This field will be calculated from quantity and price !")
employee_id = fields.Many2one('hr.employee', string="Employee", tracking=True)
x_job_card_id = fields.Many2one('res.partner', string="Vehicle Details")
#api.onchange('product_id')
def _on_change_product_id(self):
self.price = self.product_id.list_price
#api.depends('quantity', 'price')
def _compute_total(self):
print("self........", self)
for rec in self:
rec.total = rec.quantity * rec.price
Actually I wanted to add product line of selected job card into Invoice product line automatically when I select the job card.
But I am getting error as shown below :
Error
You got that error because you have no field named line_ids in job.card model. Maybe you need to change it to x_product_ids.
The TyprError (int object is not iterable) is caused by the first tuple passed to the write method :
(6, 0, 0)
Odoo expects the third parameter to be iterable. If you need to clear the list, use (5,0)
Avoid calling the write method inside an onchange function. You can read the following danger notice in the official onchange documentation:
DangerSince #onchange returns a recordset of pseudo-records, calling any one of the CRUD methods (create(), read(), write(), unlink()) on the aforementioned recordset is undefined behaviour, as they potentially do not exist in the database yet.Instead, simply set the record’s field like shown in the example above or call the update() method.
Edit:
You have two errors in get_invoice_line_vals function
1/ ValueError:
Invalid field ' price_unit' on model 'account.move.line'
You need to remove the space at the beginning.
2/ AttributeError:
'job.card.line' object has no attribute 'price_unit'.
Use the price field instead.
I have this function it filters in all selected MO's raw material lines, and then creates a report that is displayed in tree view.
But I have one problem, there can be allot lines with the same product. So my goal is to group all these lines and display them then just in one line with summed quantity.
Can someone help me with this?
class RawMaterialReport(models.Model):
_name = 'raw.material.report'
_description = 'Raw Material Report'
product_id = fields.Many2one('product.product', string='Product', required=False)
code = fields.Char(string='Code', required=True, readonly=True)
total_qty = fields.Float(string='Total Qty', digits=(6, 2), readonly=True)
virtual_qty = fields.Float(string='Forcasted Qty', digits=(6, 2), readonly=True)
origin = fields.Char(string='Origin', required=True, readonly=True)
production_id = fields.Many2one('mrp.production')
#api.multi
def open_raw_materials(self):
self.search([]).unlink()
mrp_productions = self._context.get('active_ids')
mrp_production = self.env['mrp.production'].browse(mrp_productions)
products_without_default_code = mrp_production.mapped('move_raw_ids').filtered(
lambda x: not x.product_id.default_code
)
raws = mrp_production.mapped('move_raw_ids').sorted(
key=lambda r: r.product_id.default_code
)
for r in raws:
vals = {
'product_id': r.product_id.id,
'code': r.product_id.default_code,
'total_qty': r.product_id.qty_available,
'virtual_qty': r.product_id.virtual_available,
'origin': r.reference,
'production_id': r.raw_material_production_id.id,
}
self.create(vals)
Instead of creating the record directly, keep them in dictionary grouped by product ID and when ever you find that the product all ready have a record just sum its
quantity.
#api.multi
def open_raw_materials(self):
self.search([]).unlink()
mrp_productions = self._context.get('active_ids')
mrp_production = self.env['mrp.production'].browse(mrp_productions)
products_without_default_code = mrp_production.mapped('move_raw_ids').filtered(
lambda x: not x.product_id.default_code
)
raws = mrp_production.mapped('move_raw_ids').sorted(
key=lambda r: r.product_id.default_code
)
# to group by product
recs = {}
for r in raws:
product_id = self.product_id.id
if product_id in recs:
# here just update the quantities or any other fields you want to sum
recs[product_id]['product_uom_qty'] += self.product_id.product_uom_qty
else:
# keep the record in recs
recs[product_id] = {
'product_id': r.product_id.id,
'code': r.product_id.default_code,
'total_qty': r.product_id.product_uom_qty,
'virtual_qty': r.product_id.virtual_available,
'origin': r.reference,
'production_id': r.raw_material_production_id.id,
}
for vals in recs.values():
# create records this will create a record by product
self.create(vals)
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'))