#odoo #odoo-10 #odoo-11 #odoo-12
#odoo #odoo-10 #odoo-11 #odoo-12
Вопрос:
Я добавил поле количества партии в Производственные операции комплектации. Он идеально отражает количество партии в зависимости от местоположения. Теперь проблема в том, что я не хочу показывать партии, в которых нет товара, т.е. 0 количество. Как мне этого добиться?
Вот скриншот, на котором я хочу внести изменения.
Вот код модели (stock_move_line.py ):
class StockMoveLine(models.Model):
_name = "stock.move.line"
_description = "Product Moves (Stock Move Line)"
_rec_name = "product_id"
_order = "result_package_id desc, id"
lot_id = fields.Many2one('stock.production.lot', 'Lot/Serial Number123')
x_lot_qty = fields.Float(compute="fetch_lot_wrt_location",
name="Lot Quantity",
store=True,
readonly=True,
digits=(12,3))
@api.onchange('lot_id','location_id')
def fetch_lot_wrt_location(self):
self.x_lot_qty = 0.0
for row in self:
quants = self.env['stock.quant'].search([('lot_id.id','=',row.lot_id.id)])
for quant in quants:
if row.location_id.display_name == quant.location_id.display_name:
row.x_lot_qty = quant.quantity
Вот эти виды (stock_move_views.xml ):
<field name="lot_id"
attrs="{'readonly': ['amp;amp;', ('package_level_id', '!=', False), ('parent.picking_type_entire_packs', '=', True)]}"
invisible="not context.get('show_lots_m2o')"
domain="[('product_id', '=', parent.product_id)]"
groups="stock.group_production_lot"
context="{'default_product_id': parent.product_id, 'active_picking_id': picking_id}"/>
<field name="x_lot_qty"
attrs="{'readonly': ['amp;amp;', ('package_level_id', '!=', False), ('parent.picking_type_entire_packs', '=', True)]}"
invisible="not context.get('show_lots_m2o')"
domain="[('product_id', '=', parent.product_id)]"
groups="stock.group_production_lot"
context="{'default_product_id': parent.product_id, 'active_picking_id': picking_id}"/>
Я применил фильтр по атрибуту домена, но он не работает. Как я могу ограничить количество партий количеством 0?
ОБНОВЛЕНИЕ: я попробовал следующее решение: я создал новое поле динамического выбора и попытался заполнить лоты, которые не являются пустыми в зависимости от местоположения, ниже приведен код:
@api.onchange('location_id')
def _fetch_non_empty_lots(self):
lots = []
for row in self:
quants = self.env['stock.quant'].search([('location_id.id','=',row.location_id.id), ('product_id.id', '=', row.product_id.id), ('quantity', '>', 0)])
for quant in quants:
lots.append(quant)
return lots
x_lot_id = fields.Selection(selection="_fetch_non_empty_lots", name="Non Empty Lots")
Но теперь, когда я выбираю новое местоположение, я получаю следующую ошибку:
Odoo Server Error
Traceback (most recent call last):
File "C:virtual_odoo12Scriptsodoohttp.py", line 656, in _handle_exception
return super(JsonRequest, self)._handle_exception(exception)
File "C:virtual_odoo12Scriptsodoohttp.py", line 314, in _handle_exception
raise pycompat.reraise(type(exception), exception, sys.exc_info()[2])
File "C:virtual_odoo12Scriptsodootoolspycompat.py", line 87, in reraise
raise value
File "C:virtual_odoo12Scriptsodoohttp.py", line 698, in dispatch
result = self._call_function(**self.params)
File "C:virtual_odoo12Scriptsodoohttp.py", line 346, in _call_function
return checked_call(self.db, *args, **kwargs)
File "C:virtual_odoo12Scriptsodooservicemodel.py", line 97, in wrapper
return f(dbname, *args, **kwargs)
File "C:virtual_odoo12Scriptsodoohttp.py", line 339, in checked_call
result = self.endpoint(*a, **kw)
File "C:virtual_odoo12Scriptsodoohttp.py", line 941, in __call__
return self.method(*args, **kw)
File "C:virtual_odoo12Scriptsodoohttp.py", line 519, in response_wrap
response = f(*args, **kw)
File "c:virtual_odoo12scriptsaddonswebcontrollersmain.py", line 962, in call_kw
return self._call_kw(model, method, args, kwargs)
File "c:virtual_odoo12scriptsaddonswebcontrollersmain.py", line 954, in _call_kw
return call_kw(request.env[model], method, args, kwargs)
File "C:virtual_odoo12Scriptsodooapi.py", line 759, in call_kw
return _call_kw_multi(method, model, args, kwargs)
File "C:virtual_odoo12Scriptsodooapi.py", line 746, in _call_kw_multi
result = method(recs, *args, **kwargs)
File "C:virtual_odoo12Scriptsodoomodels.py", line 5524, in onchange
record._onchange_eval(name, field_onchange[name], result)
File "C:virtual_odoo12Scriptsodoomodels.py", line 5369, in _onchange_eval
process(method_res)
File "C:virtual_odoo12Scriptsodoomodels.py", line 5355, in process
if res.get('value'):
AttributeError: 'list' object has no attribute 'get'
ОБНОВЛЕНИЕ 2:
Вместо того чтобы изменять существующий выпадающий список, я создал динамический выпадающий список. При выборе местоположения выпадающий список заполняется номерами партий, количество которых больше 0. Однако я столкнулся с основной проблемой / ошибкой:
AttributeError: 'list' object has no attribute 'get'
Вот поле выбора модели и код для его заполнения:
@api.onchange('location_id')
def _fetch_non_empty_lots(self):
quants = self.env['stock.quant'].search([('location_id.id','=',self.location_id.id),
('product_id.id', '=', self.product_id.id),
('quantity', '>', 0)])
return {str(quant.lot_id.id) :str.title(quant.lot_id.display_name) for quant in quants}
## declare field
x_lot_id = fields.Selection(selection="_fetch_non_empty_lots", name="Non Empty Lots")
Когда список пуст, ошибки нет. Когда есть непустая партия, тогда я получаю ошибку. Мне нужна некоторая помощь.
Комментарии:
1. Вы пытались определить свое поле (сохраненное, чтобы сделать его доступным для поиска) в модели партии?
Ответ №1:
Odoo определяет поле количества продукта в модели партии для производства на складе, вы можете использовать это поле в домене для фильтрации партий, и вам нужно установить store
True
значение, чтобы сделать его доступным для поиска. Если вам нужно определить новое поле, используйте ту же логику и определите его в модели партии для использования в lot_id
домене поля.
Вы получили эту ошибку, потому что Odoo ожидает словарь, а вместо него получил список.
Метод может возвращать словарь для изменения доменов полей и выдавать предупреждающее сообщение, как в старом API.
В ваших двух последних примерах вы устанавливаете атрибут выбора в строку, но selection
атрибут указывает возможные значения для этого поля. Он задается либо как список пар ( value
, string
), либо как метод модели, либо как имя метода. Вы можете найти пример в модуле website_customer.
Редактировать: (возвращает домен из onchange
метода)
Метод может возвращать словарь для изменения доменов полей и выдавать предупреждающее сообщение, как в старом API::
return {
'domain': {'other_id': [('partner_id', '=', partner_id)]},
'warning': {'title': "Warning", 'message': "What is this?"},
}
Комментарии:
1. Не могли бы вы пояснить, как я использую код, потому что я следовал той же логике, что и link, т.е. [(quant.lot_id.display_name, str.title (quant.lot_id.display_name)) для quant в quants], но получаю ту же ошибку «AttributeError: объект ‘list’ не имеет атрибута ‘get'»
2. Вы получили эту ошибку, потому что вы вернули список, а Odoo ожидает словарь. Вам необходимо удалить
onchange
декоратор из метода, который вычисляет значение выборки.3. Когда я удалил декоратор onchange, каждый раз, когда метод выбора возвращает пустое значение
4. однако я изменил оператор возврата на {str(quant.lot_id.id ) :str.title(quant.lot_id.display_name) для quant в quants}, но все равно получаю пустые данные взамен. Я отлаживал с помощью pdb, функция вызывается 4 раза, когда я меняю местоположение. При 3-м вызове функции я вижу данные в self (stock.move.line), там моя функция работает, но при вызове функции 4-го раза она не возвращает никаких лотов, поскольку self ничего не содержит
5. Я получаю акции.двигайся. строка с соответствующими данными в строке с 3-м вызовом функции. Как мне получить данные, отличные от self object than ?
Ответ №2:
Я думаю, что так и должно быть?
lot_id = fields.Many2one('stock.production.lot', 'Lot/Serial Number123'
domain="[('product_id', '=', parent.product_id),('product_qty', '>', 0)]" )
Комментарии:
1. Это не работает, поле x_lot_qty .. Он вычисляет количество продукта в номере партии, также учитывая местоположение … Я сделал что-то вроде этого lot_id = поля. Many2one(‘stock.production. лот’, ‘Лот / серийный номер1234’, домен=»[(‘product_id’, ‘=’, parent.product_id),(‘x_lot_qty’, ‘>’, 0)]»)
2.
x_lot_qty
находится наstock.move.line
, но вы ищете изstock.production.lot
3. да, потому что lot_id недоступен в stock_move_line .. и моя цель — показать только те партии, количество товара в которых больше 0 по отношению к местоположению
Ответ №3:
Насколько я понимаю, вы хотите показать только те
lots
товары, у которых более 0 товаров, в выпадающем списке ваших лотов
Вы можете попробовать это в своем XML
<field name="lot_id"
attrs="{'readonly': ['amp;amp;', ('package_level_id', '!=', False), ('parent.picking_type_entire_packs', '=', True)]}"
invisible="not context.get('show_lots_m2o')"
domain="[('product_qty', '>', 0)]" //View this
groups="stock.group_production_lot"
context="{'default_product_id': parent.product_id, 'active_picking_id': picking_id}"/>
Комментарии:
1. Это не работает … каждый раз должен быть один фильтр (‘product_id’, ‘=’, parent.product_id) .. в противном случае он будет показывать все партии продуктов, тогда product_qty не работает, поскольку он содержит общее количество продуктов не по номерам партий. поэтому я создал пользовательское вычисляемое поле с именем x_lot_qty, чтобы оно видело, какое местоположение находитсявыбрано в столбце «от», и какой продукт выбран, затем отображается количество. Поэтому нам также нужно учитывать местоположение
2. Я попробовал domain=»[(‘product_id’, ‘=’, parent.product_id),(‘xlot_qty’, ‘>’, 0)]» но получаю эту ошибку «Ошибка значения: недопустимое поле ‘xlot_qty’ в листе «<osv.ExtendedLeaf: (‘xlot_qty’, ‘>’, 0) на stock_production_lot (ctx: )>»»
3. Ты пытаешься
('xlot_qty', '>', 0)
, но я говорю('product_qty', '>', 0)
, попробуй это, мой дорогой друг 🙂4. Привет @AdamStrauss, это не работает, потому что поле ‘product_qty’ в stock.production. лот — это вычисляемое поле и поле, не относящееся к хранилищу.
5. О, понял, тогда каково решение, какие-либо рекомендации 🙂
Ответ №4:
добавьте это в свой запас.двигайтесь.линейная модель:
@api.onchange('parent.product_id')
def _onchange_product_id(self):
quants = self.env['stock.quant'].search([('product_id', '=', self.parent.product_id.id), ('quantity', '>', 0)])
return {
'domain': {
'lot_id': [
('id', 'in', quants.lot_id.ids)
],
},
}
Комментарии:
1. Он не работает.. Я изменил параметр декоратора на @api.onchange(‘lot_id’, ‘location_id’) … и добавлен фильтр местоположения на складе. quant .. но не повезло
2. Нет, не меняйте параметры декоратора onchange на ‘lot_id’ и ‘location_id’. Можете ли вы убедиться, что вызывается onchange?
3. Да, когда я меняю декоратор на location_id, он вызывается. Пожалуйста, смотрите скриншот, продукт уже выбран. Однако при изменении местоположения следует фильтровать только партии, количество которых превышает 0
4. location_id — это поле ‘From’?, если да, то измените на @api.onchange(‘location_id’), если функция вызывается, тогда вам нужно проверить результат ‘quants.lot_id.ids’, если ‘quants.lot_id.ids’ неверно, тогда проблемаэто поисковый запрос.
5. Я добавил дополнительный фильтр в ваш запрос… (‘location_id.display_name’,’=’, self.location_id.display_name) … это дает правильный результат.. но не заполняет выпадающий список