odoo 8 onchange 用于量化股票变动
odoo 8 onchange for quant in stock move
我想在库存移动表单视图中的选定位置显示选定产品的数量。到目前为止,我已经尝试了这么多,但仍然没有接近预期的结果。
.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)"/>
错误
更新
我在下面添加 stock_quant 和 stock_move class,我希望它能澄清我的问题。此外,在提出建议后,我通过更改方法进行了更新。
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
日志
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 -
您应该遵循 v8 上的新 api,而不是使用旧的 api。
查看本文档中的 "onchange: updating UI on the fly" 以获取更多信息。
https://www.odoo.com/documentation/8.0/reference/orm.html
您将在表格中输入什么
根据我的假设更改产品或位置使用搜索 api 使用 'stock.quant' 模型中的产品 ID 和位置 ID 来获取总库存。
self.env['stock.quant'].search([('product_id', '=', {product_id}),('location_id', '=', {location_id})])
我想在库存移动表单视图中的选定位置显示选定产品的数量。到目前为止,我已经尝试了这么多,但仍然没有接近预期的结果。
.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)"/>
错误
更新 我在下面添加 stock_quant 和 stock_move class,我希望它能澄清我的问题。此外,在提出建议后,我通过更改方法进行了更新。
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
日志
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 -
您应该遵循 v8 上的新 api,而不是使用旧的 api。 查看本文档中的 "onchange: updating UI on the fly" 以获取更多信息。 https://www.odoo.com/documentation/8.0/reference/orm.html
您将在表格中输入什么
根据我的假设更改产品或位置使用搜索 api 使用 'stock.quant' 模型中的产品 ID 和位置 ID 来获取总库存。
self.env['stock.quant'].search([('product_id', '=', {product_id}),('location_id', '=', {location_id})])