代码之家  ›  专栏  ›  技术社区  ›  George Daramouskas

无法使用关闭的光标

  •  1
  • George Daramouskas  · 技术社区  · 9 年前

    在对 res.partner 模型,我在第二次调用make_po方法时遇到了这个异常。如果我停止服务器并重新启动它,操作将正确继续。以下是我对make_po方法和stacktrace的重写:

    class procurement_order(osv.osv):
        _inherit = 'procurement.order'
    
        counter = 0
        global_po_id = None
        line_counter = 0
        first_line = None
        def make_po(self, cr, uid, ids, context=None):
            _logger = logging.getLogger(__name__)
            """ Resolve the purchase from procurement, which may result in a new PO creation, a new PO line creation or a quantity change on existing PO line.
            Note that some operations (as the PO creation) are made as SUPERUSER because the current user may not have rights to do it (mto product launched by a sale for example)
            @return: dictionary giving for each procurement its related resolving PO line.
            OVERRIDE: If we already have a purchase order on a draft state with the same product, do not append the lines.
            Instead create a new Purchase Order
            """
            company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id
            po_obj = self.pool.get('purchase.order')
            seq_obj = self.pool.get('ir.sequence')
            sales_orders = self.pool.get('sale.order')
            po_line = self.pool.get('purchase.order.line')
    
            # Get the procurement ID ("key" == Procurement ID, "value" == PO line)
            procurement_purchase_order = super(procurement_order, self).make_po(cr, uid, ids, context=context)
            key, value = procurement_purchase_order.popitem()
            procurement_purchase_order[key] = value
    
            # Search for the equivalent purchase.order.line
            p_o_line_returned_id = po_line.search(cr, uid, [('id', '=', value)])
            p_o_line_returned = po_line.browse(cr, uid, p_o_line_returned_id, context=context)
    
            # get purchase order from its line
            purchase_order_from_line_ID = po_obj.search(cr, uid, [('id', '=', p_o_line_returned.order_id.id)])
            purchase_order_from_line = po_obj.browse(cr, uid, purchase_order_from_line_ID, context=context)
    
            # Get me the current procurement
            current_procurement_ID = self.search(cr, uid, [('id', '=', key)])
            current_procurement = self.browse(cr, uid, current_procurement_ID, context=context)
    
            # Get me the line ids of the lines that are related to purchase_order_from_line_ID
            lines_IDS = po_line.search(cr, uid, [('order_id', '=', purchase_order_from_line_ID[0])])
            _logger.warning('lines_IDS' + str(lines_IDS))
    
            # Check the source of all the lines in thelines_IDS
            for line in po_line.browse(cr, uid, lines_IDS, context=context):
                _logger.warning('First line value ' + str(procurement_order.first_line))
                _logger.warning('')
                if line.procurement_ids != 0:
                    if procurement_order.line_counter == 0:
                        procurement_order.first_line = line 
                        procurement_order.line_counter += 1
    
                        # Compare the first line procurement.group_id with the current procurement.group_id
                    if procurement_order.first_line.procurement_ids and procurement_order.first_line.procurement_ids[0].group_id == current_procurement[0].group_id:
                        _logger.warning('GROUP IDS ARE EQUAL')
                    else:
                        _logger.warning('GROUP IDS ARE NOT EQUAL')
    
                        # if we have inequality between the group ids then that means that the current "line" was created by a different SO
                        to_remove = []
                        to_remove.append(line.id)
    
                        # from the current_procurement.group_id get the PO.line and remove it
                        temp_group_id = current_procurement[0].group_id.id
                        _logger.warning(str(temp_group_id))
                        temp_line_for_removal_ID = po_line.search(cr, uid, [('id', '=', temp_group_id)])
                        po_line.unlink(cr, uid, temp_line_for_removal_ID, context=context)
    
    
                        _logger.warning('Removed from Purchase Order ' + str(purchase_order_from_line_ID[0]) + ' Lines ' + str(to_remove))
                        pass_ids = []
                        # for all the procrements that belong to my SO
                        # for procurement in self.browse(cr, uid, ids, context=context):
                        partner = self._get_product_supplier(cr, uid, current_procurement, context=context)
                        if not partner:
                            self.message_post(cr, uid, [current_procurement.id], _('There is no supplier associated to product %s') % (current_procurement.product_id.name))
                            procurement_purchase_order[current_procurement.id] = False
                        else:
                            schedule_date = self._get_purchase_schedule_date(cr, uid, current_procurement, company, context=context)
                            purchase_date = self._get_purchase_order_date(cr, uid, current_procurement, company, schedule_date, context=context) 
                            line_vals = self._get_po_line_values_from_proc(cr, uid, current_procurement, partner, company, schedule_date, context=context)  # get the lines from here
                            name = seq_obj.get(cr, uid, 'purchase.order') or _('PO: %s') % current_procurement.name
                            po_vals = {
                            'name': name,
                            'origin': current_procurement.origin,
                            'partner_id': partner.id,
                            'location_id': current_procurement.location_id.id,
                            'picking_type_id': current_procurement.rule_id.picking_type_id.id,
                            'pricelist_id': partner.property_product_pricelist_purchase.id,
                            'currency_id': partner.property_product_pricelist_purchase and partner.property_product_pricelist_purchase.currency_id.id or current_procurement.company_id.currency_id.id,
                            'date_order': purchase_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
                            'company_id': current_procurement.company_id.id,
                            'fiscal_position': po_obj.onchange_partner_id(cr, uid, None, partner.id, context=context)['value']['fiscal_position'],
                            'payment_term_id': partner.property_supplier_payment_term.id or False,
                            'dest_address_id': current_procurement.partner_dest_id.id,
                        }
    
                        # The first time create the PO and add a line to it
                        if procurement_order.counter == 0:
                            po_id = self.create_procurement_purchase_order(cr, uid, current_procurement, po_vals, line_vals, context=context)
                            procurement_order.global_po_id = po_id
                            po_line_id = po_obj.browse(cr, uid, po_id, context=context).order_line[0].id
                            pass_ids.append(current_procurement.id)
                            procurement_purchase_order[current_procurement.id] = po_line_id
                            self.write(cr, uid, [current_procurement.id], {'purchase_line_id': po_line_id}, context=context)
                            _logger.warning('New Purchase order created ' + str(po_id))
                        else:
                            # All the other lines from the procurements will be appended here
                            proc_order = self.pool.get('procurement.order')
                            purchase_order_created = po_obj.browse(cr, uid, procurement_order.global_po_id, context=context)  # get the Purchase Order
                            line_vals = proc_order._get_po_line_values_from_proc(cr, uid, current_procurement, partner, company, schedule_date, context=context)  # Get the line from the procurement
                            po_line_obj = self.pool.get('purchase.order.line')
                            line_vals['order_id'] = purchase_order_created[0].id
                            # if there exists a line with the same id, do not add it
                            if len(po_line_obj.search(cr, uid, [('order_id', '=', purchase_order_created[0].id)])) == 0:
                                po_line_id = po_line_obj.create(cr, uid, line_vals, context=context)
                                _logger.warning('Appending line ' + str(line_vals) + 'to existing Purchase order ' + str(purchase_order_created))
                            else:
                                _logger.warning('Line has already been appended, dismissed')
                        if pass_ids:
                            self.message_post(cr, uid, pass_ids, body=_("Draft Purchase Order created"), context=context)
                        procurement_order.counter += 1
            self.pool.get('purchase.order.line').split_lines(cr, uid, [procurement_purchase_order[ids[0]]], context=context)
            return procurement_purchase_order
    

    堆栈跟踪:

    2015-09-10 13:15:11,752 1167 ERROR odoov8 openerp.http: Exception during JSON request handling.
    Traceback (most recent call last):
      File "/home/odoo/odoo/openerp/http.py", line 537, in _handle_exception
        return super(JsonRequest, self)._handle_exception(exception)
      File "/home/odoo/odoo/openerp/http.py", line 574, in dispatch
        result = self._call_function(**self.params)
      File "/home/odoo/odoo/openerp/http.py", line 310, in _call_function
        return checked_call(self.db, *args, **kwargs)
      File "/home/odoo/odoo/openerp/service/model.py", line 113, in wrapper
        return f(dbname, *args, **kwargs)
      File "/home/odoo/odoo/openerp/http.py", line 307, in checked_call
        return self.endpoint(*a, **kw)
      File "/home/odoo/odoo/openerp/http.py", line 803, in __call__
        return self.method(*args, **kw)
      File "/home/odoo/odoo/openerp/http.py", line 403, in response_wrap
        response = f(*args, **kw)
      File "/home/odoo/odoo/addons/web/controllers/main.py", line 948, in call_button
        action = self._call_kw(model, method, args, {})
      File "/home/odoo/odoo/addons/web/controllers/main.py", line 936, in _call_kw
        return getattr(request.registry.get(model), method)(request.cr, request.uid, *args, **kwargs)
      File "/home/odoo/odoo/openerp/api.py", line 241, in wrapper
        return old_api(self, *args, **kwargs)
      File "/home/odoo/odoo/addons/portal_sale/portal_sale.py", line 67, in action_button_confirm
        return super(sale_order, self).action_button_confirm(cr, uid, ids, context=context)
      File "/home/odoo/odoo/openerp/api.py", line 241, in wrapper
        return old_api(self, *args, **kwargs)
      File "/home/odoo/odoo/addons/sale/sale.py", line 605, in action_button_confirm
        self.signal_workflow(cr, uid, ids, 'order_confirm')
      File "/home/odoo/odoo/openerp/api.py", line 241, in wrapper
        return old_api(self, *args, **kwargs)
      File "/home/odoo/odoo/openerp/models.py", line 3560, in signal_workflow
        result[res_id] = workflow.trg_validate(uid, self._name, res_id, signal, cr)
      File "/home/odoo/odoo/openerp/workflow/__init__.py", line 85, in trg_validate
        return WorkflowService.new(cr, uid, res_type, res_id).validate(signal)
      File "/home/odoo/odoo/openerp/workflow/service.py", line 91, in validate
        res2 = wi.validate(signal)
      File "/home/odoo/odoo/openerp/workflow/instance.py", line 75, in validate
        wi.process(signal=signal, force_running=force_running, stack=stack)
      File "/home/odoo/odoo/openerp/workflow/workitem.py", line 120, in process
        ok = self._split_test(activity['split_mode'], signal, stack)
      File "/home/odoo/odoo/openerp/workflow/workitem.py", line 248, in _split_test
        self._join_test(t[0], t[1], stack)
      File "/home/odoo/odoo/openerp/workflow/workitem.py", line 257, in _join_test
        WorkflowItem.create(self.session, self.record, activity, inst_id, stack=stack)
      File "/home/odoo/odoo/openerp/workflow/workitem.py", line 95, in create
        workflow_item.process(stack=stack)
      File "/home/odoo/odoo/openerp/workflow/workitem.py", line 120, in process
        ok = self._split_test(activity['split_mode'], signal, stack)
      File "/home/odoo/odoo/openerp/workflow/workitem.py", line 248, in _split_test
        self._join_test(t[0], t[1], stack)
      File "/home/odoo/odoo/openerp/workflow/workitem.py", line 257, in _join_test
        WorkflowItem.create(self.session, self.record, activity, inst_id, stack=stack)
      File "/home/odoo/odoo/openerp/workflow/workitem.py", line 95, in create
        workflow_item.process(stack=stack)
      File "/home/odoo/odoo/openerp/workflow/workitem.py", line 120, in process
        ok = self._split_test(activity['split_mode'], signal, stack)
      File "/home/odoo/odoo/openerp/workflow/workitem.py", line 248, in _split_test
        self._join_test(t[0], t[1], stack)
      File "/home/odoo/odoo/openerp/workflow/workitem.py", line 257, in _join_test
        WorkflowItem.create(self.session, self.record, activity, inst_id, stack=stack)
      File "/home/odoo/odoo/openerp/workflow/workitem.py", line 95, in create
        workflow_item.process(stack=stack)
      File "/home/odoo/odoo/openerp/workflow/workitem.py", line 116, in process
        if not self._execute(activity, stack):
      File "/home/odoo/odoo/openerp/workflow/workitem.py", line 162, in _execute
        returned_action = self.wkf_expr_execute(activity)
      File "/home/odoo/odoo/openerp/workflow/workitem.py", line 313, in wkf_expr_execute
        return self.wkf_expr_eval_expr(activity['action'])
      File "/home/odoo/odoo/openerp/workflow/workitem.py", line 291, in wkf_expr_eval_expr
        result = eval(line, env, nocopy=True)
      File "/home/odoo/odoo/openerp/tools/safe_eval.py", line 314, in safe_eval
        return eval(c, globals_dict, locals_dict)
      File "", line 1, in <module>
      File "/home/odoo/odoo/openerp/api.py", line 239, in wrapper
        return new_api(self, *args, **kwargs)
      File "/home/odoo/odoo/openerp/api.py", line 547, in new_api
        result = method(self._model, cr, uid, self.ids, *args, **kwargs)
      File "/home/odoo/odoo/addons/sale/sale.py", line 765, in action_ship_create
        procurement_obj.run(cr, uid, proc_ids, context=context)
      File "/home/odoo/odoo/openerp/api.py", line 241, in wrapper
        return old_api(self, *args, **kwargs)
      File "/home/odoo/odoo/addons/procurement_jit_stock/procurement_jit_stock.py", line 30, in run
        res = super(procurement_order, self).run(cr, uid, ids, autocommit=autocommit, context=context)
      File "/home/odoo/odoo/openerp/api.py", line 241, in wrapper
        return old_api(self, *args, **kwargs)
      File "/home/odoo/odoo/addons/stock/procurement.py", line 219, in run
        self.pool.get('stock.move').action_confirm(cr, uid, move_to_confirm_ids, context=context)
      File "/home/odoo/odoo/openerp/api.py", line 241, in wrapper
        return old_api(self, *args, **kwargs)
      File "/home/odoo/odoo/addons/stock/stock.py", line 2214, in action_confirm
        self._create_procurements(cr, uid, moves, context=context)
      File "/home/odoo/odoo/openerp/api.py", line 241, in wrapper
        return old_api(self, *args, **kwargs)
      File "/home/odoo/odoo/addons/procurement_jit_stock/procurement_jit_stock.py", line 43, in _create_procurements
        self.pool['procurement.order'].run(cr, uid, res, context=context)
      File "/home/odoo/odoo/openerp/api.py", line 241, in wrapper
        return old_api(self, *args, **kwargs)
      File "/home/odoo/odoo/addons/procurement_jit_stock/procurement_jit_stock.py", line 30, in run
        res = super(procurement_order, self).run(cr, uid, ids, autocommit=autocommit, context=context)
      File "/home/odoo/odoo/openerp/api.py", line 241, in wrapper
        return old_api(self, *args, **kwargs)
      File "/home/odoo/odoo/addons/stock/procurement.py", line 210, in run
        res = super(procurement_order, self).run(cr, uid, new_ids, autocommit=autocommit, context=context)
      File "/home/odoo/odoo/openerp/api.py", line 241, in wrapper
        return old_api(self, *args, **kwargs)
      File "/home/odoo/odoo/addons/procurement/procurement.py", line 206, in run
        res = self._run(cr, uid, procurement, context=context or {})
      File "/home/odoo/odoo/openerp/api.py", line 241, in wrapper
        return old_api(self, *args, **kwargs)
      File "/home/odoo/odoo/addons/purchase/purchase.py", line 1267, in _run
        return self.make_po(cr, uid, [procurement.id], context=context)[procurement.id]
      File "/home/odoo/odoo/openerp/api.py", line 241, in wrapper
        return old_api(self, *args, **kwargs)
      File "/home/odoo/odoo/addons/glints/models/purchase.py", line 154, in make_po
        if procurement_order.first_line.procurement_ids and procurement_order.first_line.procurement_ids[0].group_id == current_procurement[0].group_id:
      File "/home/odoo/odoo/openerp/fields.py", line 817, in __get__
        self.determine_value(record)
      File "/home/odoo/odoo/openerp/fields.py", line 910, in determine_value
        record._prefetch_field(self)
      File "/home/odoo/odoo/openerp/api.py", line 239, in wrapper
        return new_api(self, *args, **kwargs)
      File "/home/odoo/odoo/openerp/models.py", line 3231, in _prefetch_field
        result = records.read(list(fnames), load='_classic_write')
      File "/home/odoo/odoo/openerp/api.py", line 239, in wrapper
        return new_api(self, *args, **kwargs)
      File "/home/odoo/odoo/openerp/models.py", line 3176, in read
        self._read_from_database(stored, inherited)
      File "/home/odoo/odoo/openerp/api.py", line 239, in wrapper
        return new_api(self, *args, **kwargs)
      File "/home/odoo/odoo/openerp/models.py", line 3300, in _read_from_database
        cr.execute(query_str, [tuple(sub_ids)] + where_params)
      File "/home/odoo/odoo/openerp/sql_db.py", line 157, in wrapper
        raise psycopg2.OperationalError(msg)
    OperationalError: Unable to use a closed cursor.
    
    1 回复  |  直到 9 年前
        1
  •  3
  •   Adrian Merrall    9 年前

    我想这是因为你误用了Odoo ORM。首先,在Odoo中,您从未声明此类类级属性。。。

    counter = 0
    global_po_id = None
    line_counter = 0
    first_line = None
    

    然后你可以在这里引用它:

    if procurement_order.first_line
    

    问题是procurement_order的类型是osv.osv,但这行代码应该使用浏览记录。当它试图跟踪并懒洋洋地从它认为是浏览记录的地方加载数据项时,它到达了一个需要使用光标的时刻,但它没有可用的光标,因此出现了错误。

    最好将osv.osv类视为一个只读元类,它描述了数据库中的表,但也允许您定义一些静态或类方法。

    您使用的采购订单应该是浏览的结果。

    my_procurement_order = self.browse(cr, uid, ids[0], context=context)
    

    下一个问题是不能在运行时将first_line这样的值分配给浏览记录,因为它们是只读的(注意,Odoo 8新API中发生了变化,但这是另一回事)。

    这里的一个常见做法是维护类似本地字典的内容,您可以参考:

    first_lines={my_proccurment_order.id:a_line}