Ich möchte meinen erstellten Datensatz zu one2many Feld hinzufügen. Es ergibt sich jedoch ValueError: Erwartetes Singleton: product.job_line (762, 763).Odoo Wie existierender Datensatz zum Feld one2many hinzugefügt wird?
Ich weiß nicht, warum es nicht in zwei Objekte trennt, aber es in ein Objekt zusammenführen, wenn JobContainer die Methode write aufrufen. Danach ergibt sich der Fehler wie zuvor.
Wie löst man das?
Hier ist mein Code von SaleOrder:
# -*- coding: utf-8 -*-
import logging
from odoo import models, fields, api
_logger = logging.getLogger(__name__)
class SaleOrder(models.Model):
_inherit = 'sale.order'
job_container = fields.One2many('job.container', 'order')
discount = fields.Float()
state = fields.Selection(
[
('draft', 'Quotation'),
('sent', 'Quotation Sent'),
('pending', 'Pending Approval'),
('sale', 'Sales Order'),
('done', 'Locked'),
('cancel', 'Cancelled'),
],
string='Status', readonly=True, copy=False, index=True,
track_visibility='onchange', default='draft'
)
@api.onchange('discount')
def _amount_all(self):
super(SaleOrder, self)._amount_all()
for order in self:
total = order.amount_total
if order.discount > 1:
total -= order.discount
else:
total -= total * order.discount
order.update({
'amount_total': total
})
@api.multi
def action_confirm(self):
if self.state != 'pending' and self.get_full_price() != self.amount_total:
self.state = 'pending'
elif self.job_container:
self.state = 'sale'
self.confirmation_date = fields.Datetime.now()
self.job_container.confirmation_date = self.confirmation_date
else:
self.create_job_container()
self.delegate_job_values()
super(SaleOrder, self).action_confirm()
def delegate_job_values(self):
total_price = self.amount_total
price_list = []
for line in self.order_line:
qty = line.product_uom_qty
product = line.product_id.product_tmpl_id
price = line.price_total*self.get_discount_percent()/qty
if price == 0:
price = line.price_total/qty
for _ in range(0, int(qty)):
price_list += product.create_price_list(price)
for index in range(0, len(self.job_container.job_lines)):
total_price -= price_list[index]
if index == len(self.job_container.job_lines)-1:
self.job_container.job_lines[index].update({
'cost': price_list[index] + total_price,
'order':self.id,
})
else:
self.job_container.job_lines[index].update({
'cost': price_list[index],
'order': self.id,
})
def get_full_price(self):
total_price = 0
for line in self.order_line:
total_price += line.product_id.product_tmpl_id.list_price*line.product_uom_qty
return total_price
def create_job_container(self):
container = self.env['job.container'].create({
'order': self.id,
'partner': self.partner_id.id,
'confirmation_date': fields.Datetime.now()
})
for line in self.order_line:
qty = line.product_uom_qty
product = line.product_id.product_tmpl_id
job_lines = []
for _ in range(0, int(qty)):
for job_line in product.create_job_lines():
_logger.info("JL : "+str(job_line))
job_lines.append(job_line.id)
# container.add_job_line(job_line)
# container.update({
# 'job_lines': [(1,job_line.id,job_line)]
# })
container.job_lines += job_line
_logger.info('Job Line '+str(job_lines))
# container.job_lines = job_lines
container.update_job_lines_left()
@api.one
def action_approve(self):
self.action_confirm()
def write(self, val):
old_state = self.state
_logger.info('Value : '+str(val))
_logger.info('Old State '+old_state)
super(SaleOrder, self).write(val)
if old_state == 'sale' and 'confirmation_date' not in val:
self.state = 'pending'
return True
def get_discount_percent(self):
if self.discount < 1:
return self.discount
else:
return self.discount/(self.amount_total+self.discount)
def update_invoice_order(self):
for invoice in self.invoice_ids:
invoice.update({'order':self.id})
@api.multi
def action_invoice_create(self, grouped=False, final=False):
super(SaleOrder, self).action_invoice_create(grouped, final)
self.update_invoice_order()
@api.one
def pending(self):
self.state = 'pending'
self.job_container.unpending()
Hier ist mein Code Hiobs Container:
# -*- coding: utf-8 -*-
from odoo import models, fields, api
import logging
_logger = logging.getLogger(__name__)
class JobContainer(models.Model):
_name = 'job.container'
_order = 'jobs_left'
_inherit = ['mail.thread']
order = fields.Many2one('sale.order', readonly=True)
partner = fields.Many2one('res.partner', readonly=True)
confirmation_date = fields.Datetime(readonly=True, track_visibility='onchange')
job_lines = fields.One2many('product.job_line', 'container')
jobs_left = fields.Integer(compute='update_job_lines_left')
to_pending = fields.Boolean()
def pending(self):
self.order.pending()
def unpending(self):
self.to_pending = False
for line in self.job_lines:
line.to_pending = False
@api.one
def update_job_lines_left(self):
left = 0
for job_line in self.job_lines:
if not job_line.is_finish and not job_line.state=='cancel':
left += 1
self.jobs_left = left
def adjust_cost(self,cost):
sum = 0
for line in self.job_lines:
if line.state=='active' and not line.is_finish:
line.cost+=round(cost/len(self.job_lines),2)
sum += line.cost
left = self.order.amount_total-sum
for line in self.job_lines:
if line.state=='active' and not line.is_finish:
line.cost+=left
break
@api.onchange('job_lines')
def notify_pending(self):
_logger.info("IN")
self.to_pending = True
@api.multi
def write(self,val):
_logger.info(val)
super(JobContainer,self).write(val)
_logger.info(str(val))
if self.to_pending:
_logger.info("INNNN")
self.pending()
return True