2017-10-16 244 views
1

我想将我创建的记录添加到one2many字段。然而,它会导致ValueError:期望的单例:product.job_line(762,763)。Odoo如何添加已存在的记录到one2many字段?

我不知道为什么它不分成两个对象,但当JobContainer调用write方法时,它合并成一个对象。之后,它会导致我之前告诉过你的错误。

如何解决这个问题?

这里是我的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() 

这是我的工作集装箱代码:

# -*- 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 

回答

1

看看这个答案:https://stackoverflow.com/a/26012940/7990703

(0, 0, { values }) link to a new record that needs to be created with the given values dictionary 
(1, ID, { values }) update the linked record with id = ID (write *values* on it) 
(2, ID)    remove and delete the linked record with id = ID (calls unlink on ID, that will delete the object completely, and the link to it as well) 

Example: 
[(0, 0, {'field_name':field_value_record1, ...}), (0, 0, {'field_name':field_value_record2, ...})]