odoo 8 onchange для количественного движения на складе - PullRequest
0 голосов
/ 15 мая 2019

Я хочу показать количество для выбранного продукта в выбранном месте в виде формы перемещения запаса. До сих пор я пробовал это много, но все еще не близко к желаемому результату.

.py

'is_quant': fields.boolean('Show Quant'),
'show_quant': fields.float(string='Quants Available' , readonly=True),

def onchange_quant(self, cr, uid, ids, is_quant, product_id, location_id, show_quant):

    if is_quant:
        show_quant = self.pool.get('stock.quant').browse(cr, uid, product_id, location_id).qty
        return {'value': {'show_quant': show_quant}}
    else:
        pass

.xml

<field name="is_quant" on_change="onchange_quant(is_quant, product_id, location_id, show_quant)"/>

ERROR

onchage error message

UPDATE Я добавляю классы stock_quant и stock_move ниже, надеюсь, это проясняет мою точку зрения. Также после предложений я обновил метод изменения.

stock.py

class stock_quant(osv.osv):
    """
    Quants are the smallest unit of stock physical instances
    """
    _name = "stock.quant"
    _description = "Quants"
    _columns = {
        'name': fields.function(_get_quant_name, type='char', string='Identifier'),
        'product_id': fields.many2one('product.product', 'Product', required=True, ondelete="restrict", readonly=True, select=True),
        'location_id': fields.many2one('stock.location', 'Location', required=True, ondelete="restrict", readonly=True, select=True, auto_join=True),
        'qty': fields.float('Quantity', required=True, help="Quantity of products in this quant, in the default unit of measure of the product", readonly=True, select=True),
        'package_id': fields.many2one('stock.quant.package', string='Package', help="The package containing this quant", readonly=True, select=True),
        'packaging_type_id': fields.related('package_id', 'packaging_id', type='many2one', relation='product.packaging', string='Type of packaging', readonly=True, store=True),
        'reservation_id': fields.many2one('stock.move', 'Reserved for Move', help="The move the quant is reserved for", readonly=True, select=True),
        'lot_id': fields.many2one('stock.production.lot', 'Lot', readonly=True, select=True, ondelete="restrict"),
        'cost': fields.float('Unit Cost'),
        'owner_id': fields.many2one('res.partner', 'Owner', help="This is the owner of the quant", readonly=True, select=True),

        'create_date': fields.datetime('Creation Date', readonly=True),
        'in_date': fields.datetime('Incoming Date', readonly=True, select=True),

        'history_ids': fields.many2many('stock.move', 'stock_quant_move_rel', 'quant_id', 'move_id', 'Moves', help='Moves that operate(d) on this quant', copy=False),
        'company_id': fields.many2one('res.company', 'Company', help="The company to which the quants belong", required=True, readonly=True, select=True),
        'inventory_value': fields.function(_calc_inventory_value, string="Inventory Value", type='float', readonly=True),

        # Used for negative quants to reconcile after compensated by a new positive one
        'propagated_from_id': fields.many2one('stock.quant', 'Linked Quant', help='The negative quant this is coming from', readonly=True, select=True),
        'negative_move_id': fields.many2one('stock.move', 'Move Negative Quant', help='If this is a negative quant, this will be the move that caused this negative quant.', readonly=True),
        'negative_dest_location_id': fields.related('negative_move_id', 'location_dest_id', type='many2one', relation='stock.location', string="Negative Destination Location", readonly=True,
                                                    help="Technical field used to record the destination location of a move that created a negative quant"),
    }


class stock_move(osv.osv):
    _name = "stock.move"
    _description = "Stock Move"
    _order = 'date_expected desc, id'
    _log_create = False
    _columns = {
        'name': fields.char('Description', required=True, select=True),
        'priority': fields.selection(procurement.PROCUREMENT_PRIORITIES, 'Priority'),
        'create_date': fields.datetime('Creation Date', readonly=True, select=True),
        'date': fields.datetime('Date', required=True, select=True, help="Move date: scheduled date until move is done, then date of actual move processing", states={'done': [('readonly', True)]}),
        'date_expected': fields.datetime('Expected Date', states={'done': [('readonly', True)]}, required=True, select=True, help="Scheduled date for the processing of this move"),
        'product_id': fields.many2one('product.product', 'Product', required=True, select=True, domain=[('type', '<>', 'service')], states={'done': [('readonly', True)]}),
        'product_qty': fields.function(_quantity_normalize, fnct_inv=_set_product_qty, type='float', digits=0, store=True, string='Quantity',
            help='Quantity in the default UoM of the product'),
        'product_uom_qty': fields.float('Quantity', digits_compute=dp.get_precision('Product Unit of Measure'),
            required=True, states={'done': [('readonly', True)]},
            help="This is the quantity of products from an inventory "
                "point of view. For moves in the state 'done', this is the "
                "quantity of products that were actually moved. For other "
                "moves, this is the quantity of product that is planned to "
                "be moved. Lowering this quantity does not generate a "
                "backorder. Changing this quantity on assigned moves affects "
                "the product reservation, and should be done with care."
        ),
        'product_uom': fields.many2one('product.uom', 'Unit of Measure', required=True, states={'done': [('readonly', True)]}),
        'product_uos_qty': fields.float('Quantity (UOS)', digits_compute=dp.get_precision('Product Unit of Measure'), states={'done': [('readonly', True)]}),
        'product_uos': fields.many2one('product.uom', 'Product UOS', states={'done': [('readonly', True)]}),
        'product_tmpl_id': fields.related('product_id', 'product_tmpl_id', type='many2one', relation='product.template', string='Product Template'),

        'product_packaging': fields.many2one('product.packaging', 'Prefered Packaging', help="It specifies attributes of packaging like type, quantity of packaging,etc."),

        'location_id': fields.many2one('stock.location', 'Source Location', required=True, select=True, auto_join=True,
                                       states={'done': [('readonly', True)]}, help="Sets a location if you produce at a fixed location. This can be a partner location if you subcontract the manufacturing operations."),
        'location_dest_id': fields.many2one('stock.location', 'Destination Location', required=True, states={'done': [('readonly', True)]}, select=True,
                                            auto_join=True, help="Location where the system will stock the finished products."),

        'partner_id': fields.many2one('res.partner', 'Destination Address ', states={'done': [('readonly', True)]}, help="Optional address where goods are to be delivered, specifically used for allotment"),


        'move_dest_id': fields.many2one('stock.move', 'Destination Move', help="Optional: next stock move when chaining them", select=True, copy=False),
        'move_orig_ids': fields.one2many('stock.move', 'move_dest_id', 'Original Move', help="Optional: previous stock move when chaining them", select=True),

        'picking_id': fields.many2one('stock.picking', 'Reference', select=True, states={'done': [('readonly', True)]}),
        'note': fields.text('Notes'),
        'state': fields.selection([('draft', 'New'),
                                   ('cancel', 'Cancelled'),
                                   ('waiting', 'Waiting Another Move'),
                                   ('confirmed', 'Waiting Availability'),
                                   ('assigned', 'Available'),
                                   ('done', 'Done'),
                                   ], 'Status', readonly=True, select=True, copy=False,
                 help= "* New: When the stock move is created and not yet confirmed.\n"\
                       "* Waiting Another Move: This state can be seen when a move is waiting for another one, for example in a chained flow.\n"\
                       "* Waiting Availability: This state is reached when the procurement resolution is not straight forward. It may need the scheduler to run, a component to me manufactured...\n"\
                       "* Available: When products are reserved, it is set to \'Available\'.\n"\
                       "* Done: When the shipment is processed, the state is \'Done\'."),
        'partially_available': fields.boolean('Partially Available', readonly=True, help="Checks if the move has some stock reserved", copy=False),
        'price_unit': fields.float('Unit Price', help="Technical field used to record the product cost set by the user during a picking confirmation (when costing method used is 'average price' or 'real'). Value given in company currency and in product uom."),  # as it's a technical field, we intentionally don't provide the digits attribute

        'company_id': fields.many2one('res.company', 'Company', required=True, select=True),
        'split_from': fields.many2one('stock.move', string="Move Split From", help="Technical field used to track the origin of a split move, which can be useful in case of debug", copy=False),
        'backorder_id': fields.related('picking_id', 'backorder_id', type='many2one', relation="stock.picking", string="Back Order of", select=True),
        'origin': fields.char("Source"),
        'procure_method': fields.selection([('make_to_stock', 'Default: Take From Stock'), ('make_to_order', 'Advanced: Apply Procurement Rules')], 'Supply Method', required=True,
                                           help="""By default, the system will take from the stock in the source location and passively wait for availability. The other possibility allows you to directly create a procurement on the source location (and thus ignore its current stock) to gather products. If we want to chain moves and have this one to wait for the previous, this second option should be chosen."""),

        # used for colors in tree views:
        'scrapped': fields.related('location_dest_id', 'scrap_location', type='boolean', relation='stock.location', string='Scrapped', readonly=True),

        'quant_ids': fields.many2many('stock.quant', 'stock_quant_move_rel', 'move_id', 'quant_id', 'Moved Quants', copy=False),
        'reserved_quant_ids': fields.one2many('stock.quant', 'reservation_id', 'Reserved quants'),
        'linked_move_operation_ids': fields.one2many('stock.move.operation.link', 'move_id', string='Linked Operations', readonly=True, help='Operations that impact this move for the computation of the remaining quantities'),
        'remaining_qty': fields.function(_get_remaining_qty, type='float', string='Remaining Quantity', digits=0,
                                         states={'done': [('readonly', True)]}, help="Remaining Quantity in default UoM according to operations matched with this move"),
        'procurement_id': fields.many2one('procurement.order', 'Procurement'),
        'group_id': fields.many2one('procurement.group', 'Procurement Group'),
        'rule_id': fields.many2one('procurement.rule', 'Procurement Rule', help='The pull rule that created this stock move'),
        'push_rule_id': fields.many2one('stock.location.path', 'Push Rule', help='The push rule that created this stock move'),
        'propagate': fields.boolean('Propagate cancel and split', help='If checked, when this move is cancelled, cancel the linked move too'),
        'picking_type_id': fields.many2one('stock.picking.type', 'Picking Type'),
        'inventory_id': fields.many2one('stock.inventory', 'Inventory'),
        'lot_ids': fields.function(_get_lot_ids, type='many2many', relation='stock.production.lot', string='Lots'),
        'origin_returned_move_id': fields.many2one('stock.move', 'Origin return move', help='move that created the return move', copy=False),
        'returned_move_ids': fields.one2many('stock.move', 'origin_returned_move_id', 'All returned moves', help='Optional: all returned moves created from this move'),
        'reserved_availability': fields.function(_get_reserved_availability, type='float', string='Quantity Reserved', readonly=True, help='Quantity that has already been reserved for this move'),
        'availability': fields.function(_get_product_availability, type='float', string='Quantity Available', readonly=True, help='Quantity in stock that can still be reserved for this move'),
        'string_availability_info': fields.function(_get_string_qty_information, type='text', string='Availability', readonly=True, help='Show various information on stock availability for this move'),
        'restrict_lot_id': fields.many2one('stock.production.lot', 'Lot', help="Technical field used to depict a restriction on the lot of quants to consider when marking this move as 'done'"),
        'restrict_partner_id': fields.many2one('res.partner', 'Owner ', help="Technical field used to depict a restriction on the ownership of quants to consider when marking this move as 'done'"),
        'route_ids': fields.many2many('stock.location.route', 'stock_location_route_move', 'move_id', 'route_id', 'Destination route', help="Preferred route to be followed by the procurement order"),
        'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse', help="Technical field depicting the warehouse to consider for the route selection on the next procurement (if any)."),
        # 'line_no': fields.function(_calc_line_no, type='integer', string='Serial No.', readonly=True),
        'is_quant': fields.boolean('Show Quant'),
        'show_quant': fields.float(string='Quants Available', readonly=True),
    }

@api.onchange('is_quant')
    def onchange_quant(self):
        is_quant = self.is_quant
        show_quant = self.show_quant
        product_id = self.product_id.id
        location_id = self.location_id.id
        if is_quant:
            stock = self.env['stock.quant'].search([('product_id', '=', product_id),('location_id', '=', location_id)])
            # product = self.env['product.product'].browse({'product_id', '=', product_id})
            show_quant = stock.qty
            return show_quant
        else:
            pass

LOG

2019-05-22 12:07:26,298 9608 INFO printlinkstore werkzeug: 127.0.0.1 - - [22/May/2019 12:07:26] "POST /longpolling/poll HTTP/1.1" 200 -
2019-05-22 12:07:32,947 9608 INFO printlinkstore werkzeug: 127.0.0.1 - - [22/May/2019 12:07:32] "POST /web/dataset/call_kw/stock.picking/fields_view_get HTTP/1.1" 200 -
2019-05-22 12:07:33,469 9608 INFO printlinkstore werkzeug: 127.0.0.1 - - [22/May/2019 12:07:33] "POST /web/dataset/call_kw/stock.picking/default_get HTTP/1.1" 200 -
2019-05-22 12:07:33,858 9608 INFO printlinkstore werkzeug: 127.0.0.1 - - [22/May/2019 12:07:33] "POST /web/dataset/call_kw/stock.picking/onchange HTTP/1.1" 200 -
2019-05-22 12:07:33,946 9608 INFO printlinkstore werkzeug: 127.0.0.1 - - [22/May/2019 12:07:33] "POST /web/dataset/call_kw/stock.picking.type/name_get HTTP/1.1" 200 -
2019-05-22 12:07:33,976 9608 INFO printlinkstore werkzeug: 127.0.0.1 - - [22/May/2019 12:07:33] "POST /web/dataset/call_kw/res.company/name_search HTTP/1.1" 200 -
2019-05-22 12:07:34,012 9608 INFO printlinkstore werkzeug: 127.0.0.1 - - [22/May/2019 12:07:34] "POST /web/dataset/call_kw/product.uom/name_get HTTP/1.1" 200 -
2019-05-22 12:07:34,019 9608 INFO printlinkstore werkzeug: 127.0.0.1 - - [22/May/2019 12:07:34] "POST /web/dataset/call_kw/stock.picking/read_followers_data HTTP/1.1" 200 -
2019-05-22 12:07:34,190 9608 INFO ? werkzeug: 127.0.0.1 - - [22/May/2019 12:07:34] "GET /web/static/src/img/down-arrow.png HTTP/1.1" 200 -
2019-05-22 12:07:34,262 9608 INFO ? werkzeug: 127.0.0.1 - - [22/May/2019 12:07:34] "GET /web/static/src/img/ui/field_calendar.png HTTP/1.1" 200 -
2019-05-22 12:07:34,391 9608 INFO printlinkstore werkzeug: 127.0.0.1 - - [22/May/2019 12:07:34] "POST /web/dataset/call_kw/stock.move/fields_view_get HTTP/1.1" 200 -
2019-05-22 12:07:36,065 9608 INFO printlinkstore werkzeug: 127.0.0.1 - - [22/May/2019 12:07:36] "POST /web/dataset/call_kw/stock.move/fields_view_get HTTP/1.1" 200 -
2019-05-22 12:07:36,463 9608 INFO printlinkstore werkzeug: 127.0.0.1 - - [22/May/2019 12:07:36] "POST /web/dataset/call_kw/stock.move/default_get HTTP/1.1" 200 -
2019-05-22 12:07:36,812 9608 INFO printlinkstore werkzeug: 127.0.0.1 - - [22/May/2019 12:07:36] "POST /web/dataset/call_kw/stock.move/onchange HTTP/1.1" 200 -
2019-05-22 12:07:36,970 9608 INFO printlinkstore werkzeug: 127.0.0.1 - - [22/May/2019 12:07:36] "POST /web/dataset/call_kw/stock.location/name_get HTTP/1.1" 200 -
2019-05-22 12:07:37,003 9608 INFO ? werkzeug: 127.0.0.1 - - [22/May/2019 12:07:37] "GET /web/static/src/img/icons/terp-gtk-jump-to-ltr.png HTTP/1.1" 200 -
2019-05-22 12:07:37,003 9608 INFO printlinkstore werkzeug: 127.0.0.1 - - [22/May/2019 12:07:37] "POST /web/dataset/call_kw/stock.location/name_get HTTP/1.1" 200 -
2019-05-22 12:07:37,177 9608 INFO printlinkstore werkzeug: 127.0.0.1 - - [22/May/2019 12:07:37] "POST /web/dataset/call_kw/stock.quant/fields_view_get HTTP/1.1" 200 -
2019-05-22 12:07:37,740 9608 INFO printlinkstore werkzeug: 127.0.0.1 - - [22/May/2019 12:07:37] "POST /web/dataset/call_kw/stock.picking.type/name_get HTTP/1.1" 200 -
2019-05-22 12:07:39,138 9608 INFO printlinkstore werkzeug: 127.0.0.1 - - [22/May/2019 12:07:39] "POST /web/dataset/call_kw/product.product/name_search HTTP/1.1" 200 -
2019-05-22 12:07:39,592 9608 INFO printlinkstore werkzeug: 127.0.0.1 - - [22/May/2019 12:07:39] "POST /web/dataset/call_kw/product.product/name_search HTTP/1.1" 200 -
2019-05-22 12:07:41,573 9608 INFO printlinkstore werkzeug: 127.0.0.1 - - [22/May/2019 12:07:41] "POST /web/dataset/call_kw/stock.move/onchange HTTP/1.1" 200 -
2019-05-22 12:07:41,903 9608 INFO printlinkstore werkzeug: 127.0.0.1 - - [22/May/2019 12:07:41] "POST /web/dataset/call_kw/product.uom/name_get HTTP/1.1" 200 -
2019-05-22 12:07:45,068 9608 INFO printlinkstore werkzeug: 127.0.0.1 - - [22/May/2019 12:07:45] "POST /web/dataset/call_kw/stock.location/name_search HTTP/1.1" 200 -
2019-05-22 12:07:45,572 9608 INFO printlinkstore werkzeug: 127.0.0.1 - - [22/May/2019 12:07:45] "POST /web/dataset/call_kw/stock.location/name_search HTTP/1.1" 200 -
2019-05-22 12:07:46,187 9608 INFO printlinkstore werkzeug: 127.0.0.1 - - [22/May/2019 12:07:46] "POST /web/dataset/call_kw/stock.location/name_search HTTP/1.1" 200 -
2019-05-22 12:07:49,542 9608 ERROR printlinkstore openerp.http: Exception during JSON request handling.
Traceback (most recent call last):
  File "C:\Program Files\Odoo 8.0-20150515\server\.\openerp\http.py", line 530, in _handle_exception
  File "C:\Program Files\Odoo 8.0-20150515\server\.\openerp\http.py", line 567, in dispatch
  File "C:\Program Files\Odoo 8.0-20150515\server\.\openerp\http.py", line 303, in _call_function
  File "C:\Program Files\Odoo 8.0-20150515\server\.\openerp\service\model.py", line 113, in wrapper
  File "C:\Program Files\Odoo 8.0-20150515\server\.\openerp\http.py", line 300, in checked_call
  File "C:\Program Files\Odoo 8.0-20150515\server\.\openerp\http.py", line 796, in __call__
  File "C:\Program Files\Odoo 8.0-20150515\server\.\openerp\http.py", line 396, in response_wrap
  File "C:\Program Files\Odoo 8.0-20150515\server\openerp\addons\web\controllers\main.py", line 936, in call_kw
  File "C:\Program Files\Odoo 8.0-20150515\server\openerp\addons\web\controllers\main.py", line 928, in _call_kw
  File "C:\Program Files\Odoo 8.0-20150515\server\.\openerp\api.py", line 241, in wrapper
  File "C:\Program Files\Odoo 8.0-20150515\server\.\openerp\api.py", line 363, in old_api
  File "C:\Program Files\Odoo 8.0-20150515\server\.\openerp\models.py", line 5864, in onchange
  File "C:\Program Files\Odoo 8.0-20150515\server\.\openerp\models.py", line 5748, in _onchange_eval
TypeError: argument of type 'float' is not iterable
2019-05-22 12:07:49,548 9608 INFO printlinkstore werkzeug: 127.0.0.1 - - [22/May/2019 12:07:49] "POST /web/dataset/call_kw/stock.move/onchange HTTP/1.1" 200 -

Ответы [ 2 ]

0 голосов
/ 15 мая 2019

Каким будет ваш ввод в форму

Согласно моим предположениям продукт или местоположение Onchange Используйте API поиска, используя идентификатор продукта и идентификатор местоположения в модели stock.quant, чтобы получить общий запас.

self.env['stock.quant'].search([('product_id', '=', {product_id}),('location_id', '=', {location_id})])

0 голосов
/ 15 мая 2019

Вы должны следовать новому API на v8 вместо того, чтобы использовать старый API. Проверьте «onchange: обновление пользовательского интерфейса на лету» в этом документе для получения дополнительной информации. https://www.odoo.com/documentation/8.0/reference/orm.html

...