From 94f2fca489d2d9224d3f9faf8556a3993ce5dda8 Mon Sep 17 00:00:00 2001 From: juanjo-nan <57089222+juanjo-nan@users.noreply.github.com> Date: Fri, 6 Aug 2021 10:50:35 +0200 Subject: [PATCH] Move POC picking to stock_scanner module. (#1) Fix show last product. Now we order the pending moves by locations. If there are diferents locations, we show the name before the move. Fix picking more than one unit at the same time. 046607 --- __init__.py | 7 + picking.py | 161 +++++++++++++++++++++ picking.xml | 33 +++++ stock.py | 25 +++- tryton.cfg | 1 + view/stock_picking_shipment_out_result.xml | 12 ++ view/stock_picking_shipment_out_scan.xml | 9 ++ view/stock_picking_shipment_out_start.xml | 9 ++ 8 files changed, 251 insertions(+), 6 deletions(-) create mode 100644 picking.py create mode 100644 picking.xml create mode 100644 view/stock_picking_shipment_out_result.xml create mode 100644 view/stock_picking_shipment_out_scan.xml create mode 100644 view/stock_picking_shipment_out_start.xml diff --git a/__init__.py b/__init__.py index cb43bc5..4caf3f1 100755 --- a/__init__.py +++ b/__init__.py @@ -2,6 +2,7 @@ # copyright notices and license terms. from trytond.pool import Pool from . import stock +from . import picking def register(): @@ -11,4 +12,10 @@ def register(): stock.ShipmentIn, stock.ShipmentOut, stock.ShipmentOutReturn, + picking.StockPickingShipmentOutAsk, + picking.StockPickingShipmentOutScan, + picking.StockPickingShipmentOutResult, module='stock_scanner', type_='model') + Pool.register( + picking.StockPickingShipmentOut, + module='stock_scanner', type_='wizard') \ No newline at end of file diff --git a/picking.py b/picking.py new file mode 100644 index 0000000..7d5c509 --- /dev/null +++ b/picking.py @@ -0,0 +1,161 @@ +# The COPYRIGHT file at the top level of this repository contains the full +# copyright notices and license terms. +from trytond.model import ModelView, fields +from trytond.wizard import Wizard, StateTransition, StateView, Button +from trytond.pool import Pool + + +class StockPickingShipmentOutAsk(ModelView): + 'Stock Picking Shipment Out Ask' + __name__ = 'stock.picking.shipment.out.ask' + shipment = fields.Char('Shipment') + to_pick = fields.Selection('get_to_pick', 'To Pick', sort=True) + + @classmethod + def get_to_pick(cls): + pool = Pool() + Shipment = pool.get('stock.shipment.out') + return [(s.id, s.rec_name) for s in Shipment.search([ + ('state', '=', 'assigned'), + ])] + + +class StockPickingShipmentOutScan(ModelView): + 'Stock Picking Shipment Out Scan' + __name__ = 'stock.picking.shipment.out.scan' + shipment = fields.Many2One('stock.shipment.out', 'Shipment', readonly=True) + product = fields.Many2One('product.product', 'Product', readonly=True) + to_pick = fields.Char('To pick') + pending_moves = fields.Text('APP Pending Moves', readonly=True) + + +class StockPickingShipmentOutResult(ModelView): + "Stock Picking Shipment Out Result" + __name__ = 'stock.picking.shipment.out.result' + shipment = fields.Many2One('stock.shipment.out', 'Shipment', readonly=True) + note = fields.Text('Note', readonly=True) + + +class StockPickingShipmentOut(Wizard): + "Stock Picking Shipment Out Ask" + __name__ = 'stock.picking.shipment.out' + start_state = 'ask' + ask = StateView('stock.picking.shipment.out.ask', + 'stock_scanner.stock_picking_shipment_out_start', [ + Button('Cancel', 'end', 'tryton-cancel'), + Button('Scan', 'scan', 'tryton-ok', True), + ]) + scan = StateView('stock.picking.shipment.out.scan', + 'stock_scanner.stock_picking_shipment_out_scan', [ + Button('Cancel', 'end', 'tryton-cancel'), + Button('Back', 'ask', 'tryton-back'), + Button('Pick', 'pick', 'tryton-launch', True), + Button('Packed', 'packed', 'tryton-ok'), + ]) + pick = StateTransition() + packed = StateTransition() + result = StateView('stock.picking.shipment.out.result', + 'stock_scanner.stock_picking_shipment_out_result', [ + Button('Start', 'ask', 'tryton-back', True), + Button('Done', 'end', 'tryton-ok'), + ]) + + def transition_pick(self): + pool = Pool() + Shipment = pool.get('stock.shipment.out') + + shipment = Shipment(self.scan.shipment) + + def qty(value): + try: + return float(value) + except ValueError: + return False + + shipment = Shipment(self.scan.shipment) + to_pick = self.scan.to_pick + quantity = qty(to_pick) + + if shipment.scanned_product and quantity and len(to_pick) < 5: + shipment.scanned_quantity = shipment.scanned_uom.round(quantity) + shipment.save() + Shipment.scan([shipment]) + shipment = Shipment(shipment.id) + else: + for move in shipment.pending_moves: + if move.matches_scan(to_pick): + self.scan.product = move.product + shipment.scanned_product = move.product + shipment.scanned_quantity = 1 + shipment.on_change_scanned_product() + shipment.save() + Shipment.scan([shipment]) + shipment.scanned_product = move.product + shipment.save() + break + else: + self.scan.product = None + return 'scan' + + def transition_packed(self): + pool = Pool() + Shipment = pool.get('stock.shipment.out') + + shipment = Shipment(self.scan.shipment) + Shipment.assign([shipment]) + Shipment.pack([shipment]) + + return 'result' + + def default_scan(self, fields): + pool = Pool() + Shipment = pool.get('stock.shipment.out') + Location = pool.get('stock.location') + + # Get storage_location locations + storages = Location.search([('type', '=', 'warehouse')]) + storage_locations = [] + for storage in storages: + storage_locations.append(storage.storage_location) + + if self.ask.to_pick is not None: + shipment = Shipment(self.ask.to_pick) + else: + shipments = Shipment.search([ + ('state', '=', 'assigned'), + ('number', '=', self.ask.shipment), + ], limit=1) + if not shipments: + return {} + shipment, = shipments + + defaults = {} + defaults['shipment'] = shipment.id + if hasattr(self.scan, 'product'): + defaults['product'] = self.scan.product and self.scan.product.id + + pending_moves = [] + locations_move = {} + for move in shipment.pending_moves: + locations_move.setdefault(move.from_location, []) + locations_move[move.from_location].append(move) + + for location in sorted(locations_move, key=lambda x: x.name): + if location not in storage_locations: + pending_moves.append( + u'