From 088e87a3affebb4ebbf1fc4aaff5f09440a2d3d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 24 Sep 2012 22:18:21 +0200 Subject: [PATCH] Active Record --- __init__.py | 15 ++++++ product.py | 26 +++++------ stock.py | 129 +++++++++++++++++++++++----------------------------- 3 files changed, 83 insertions(+), 87 deletions(-) diff --git a/__init__.py b/__init__.py index cac1f0ea87..a41bf3ca51 100644 --- a/__init__.py +++ b/__init__.py @@ -1,5 +1,20 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of this #repository contains the full copyright notices and license terms. +from trytond.pool import Pool from .stock import * from .product import * + + +def register(): + Pool.register( + Lot, + LotType, + Move, + ShipmentIn, + ShipmentOut, + ShipmentOutReturn, + Template, + Product, + TemplateLotType, + module='stock_lot', type_='model') diff --git a/product.py b/product.py index f1ce0f512e..87debcf4f5 100644 --- a/product.py +++ b/product.py @@ -1,11 +1,15 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. -from trytond.model import Model, ModelSQL, fields +from trytond.model import ModelSQL, fields from trytond.pyson import Eval +from trytond.pool import PoolMeta + +__all__ = ['Template', 'Product', 'TemplateLotType'] +__metaclass__ = PoolMeta -class Template(Model): - _name = 'product.template' +class Template: + __name__ = 'product.template' # TODO to replace with a Multiple Selection lot_required = fields.Many2Many('product.template-stock.lot.type', @@ -16,28 +20,22 @@ class Template(Model): }, depends=['type']) -Template() +class Product: + __name__ = 'product.product' -class Product(Model): - _name = 'product.product' - - def lot_is_required(self, product, from_, to): + def lot_is_required(self, from_, to): 'Is product lot required for move with "from_" and "to" location ?' - lot_required = [t.code for t in product.lot_required] + lot_required = [t.code for t in self.lot_required] for location in (from_, to): if location.type in lot_required: return True -Product() - class TemplateLotType(ModelSQL): 'Template - Stock Lot Type' - _name = 'product.template-stock.lot.type' + __name__ = 'product.template-stock.lot.type' template = fields.Many2One('product.template', 'Template', required=True, select=True) type = fields.Many2One('stock.lot.type', 'Type', required=True) - -TemplateLotType() diff --git a/stock.py b/stock.py index fb02e70a2f..3a9bfb114d 100644 --- a/stock.py +++ b/stock.py @@ -1,36 +1,31 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. -from trytond.model import Model, ModelView, ModelSQL, Workflow, fields +from trytond.model import ModelView, ModelSQL, Workflow, fields from trytond.pyson import Eval -from trytond.pool import Pool +from trytond.pool import Pool, PoolMeta + +__all__ = ['Lot', 'LotType', 'Move', 'ShipmentIn', 'ShipmentOut', + 'ShipmentOutReturn'] +__metaclass__ = PoolMeta class Lot(ModelSQL, ModelView): "Stock Lot" - _name = 'stock.lot' - _description = __doc__ + __name__ = 'stock.lot' _rec_name = 'number' - number = fields.Char('Number', required=True, select=True) product = fields.Many2One('product.product', 'Product', required=True) -Lot() - class LotType(ModelSQL, ModelView): "Stock Lot Type" - _name = 'stock.lot.type' - _description = __doc__ - + __name__ = 'stock.lot.type' name = fields.Char('Name', required=True, translate=True) code = fields.Char('Code', required=True) -LotType() - - -class Move(Model): - _name = 'stock.move' +class Move: + __name__ = 'stock.move' lot = fields.Many2One('stock.lot', 'Lot', domain=[ ('product', '=', Eval('product')), @@ -40,66 +35,61 @@ class Move(Model): }, depends=['state', 'product']) - def __init__(self): - super(Move, self).__init__() - self._error_messages.update({ + @classmethod + def __setup__(cls): + super(Move, cls).__setup__() + cls._error_messages.update({ 'lot_required': 'Lot is required for move of product "%s"!', }) - def check_lot(self, ids): + @classmethod + def check_lot(cls, moves): "Check if lot is required" - pool = Pool() - product_obj = pool.get('product.product') - for move in self.browse(ids): + for move in moves: if (move.state == 'done' and not move.lot - and product_obj.lot_is_required(move.product, + and move.product.lot_is_required( move.from_location, move.to_location)): - self.raise_user_error('lot_required', (move.product.rec_name,)) + cls.raise_user_error('lot_required', (move.product.rec_name,)) - def create(self, values): - new_id = super(Move, self).create(values) - self.check_lot([new_id]) - return new_id + @classmethod + def create(cls, values): + move = super(Move, cls).create(values) + cls.check_lot([move]) + return move - def write(self, ids, values): - result = super(Move, self).write(ids, values) - if isinstance(ids, (int, long)): - ids = [ids] - self.check_lot(ids) - return result - -Move() + @classmethod + def write(cls, moves, values): + super(Move, cls).write(moves, values) + cls.check_lot(moves) -class ShipmentIn(Model): - _name = 'stock.shipment.in' +class ShipmentIn: + __name__ = 'stock.shipment.in' - def _get_inventory_moves(self, incoming_move): - result = super(ShipmentIn, self)._get_inventory_moves(incoming_move) - if result: + @classmethod + def _get_inventory_moves(cls, incoming_move): + result = super(ShipmentIn, cls)._get_inventory_moves(incoming_move) + if result and incoming_move.lot: result['lot'] = incoming_move.lot.id return result -ShipmentIn() +class ShipmentOut: + __name__ = 'stock.shipment.out' -class ShipmentOut(Model): - _name = 'stock.shipment.out' - + @classmethod @ModelView.button @Workflow.transition('packed') - def pack(self, ids): + def pack(cls, shipments): pool = Pool() - uom_obj = pool.get('product.uom') - move_obj = pool.get('stock.move') + Uom = pool.get('product.uom') + Move = pool.get('stock.move') - super(ShipmentOut, self).pack(ids) - - shipments = self.browse(ids) + super(ShipmentOut, cls).pack(shipments) # Unassign move to allow update - move_obj.write([m.id for s in shipments for m in s.outgoing_moves + Move.write([m for s in shipments for m in s.outgoing_moves if m.state not in ('done', 'cancel')], { 'state': 'draft', }) @@ -112,47 +102,40 @@ class ShipmentOut(Model): for move in shipment.inventory_moves: if not move.lot: continue - quantity = uom_obj.compute_qty(move.uom, move.quantity, + quantity = Uom.compute_qty(move.uom, move.quantity, move.product.default_uom, round=False) outgoing_moves = outgoing_by_product[move.product.id] while outgoing_moves and quantity > 0: out_move = outgoing_moves.pop() - out_quantity = uom_obj.compute_qty(out_move.uom, + out_quantity = Uom.compute_qty(out_move.uom, out_move.quantity, out_move.product.default_uom, round=False) if quantity < out_quantity: - outgoing_moves.append(move_obj.browse( - move_obj.copy(out_move.id, default={ - 'quantity': out_quantity - quantity, - }))) - move_obj.write(out_move.id, { + outgoing_moves.extend(Move.copy([out_move], default={ + 'quantity': out_quantity - quantity, + })) + Move.write([out_move], { 'quantity': quantity, }) - move_obj.write(out_move.id, { + Move.write([out_move], { 'lot': move.lot.id, }) quantity -= out_quantity assert quantity <= 0 - # Reset function field cache - shipments = self.browse(ids) - - move_obj.write([m.id for s in shipments for m in s.outgoing_moves + Move.write([m for s in shipments for m in s.outgoing_moves if m.state != 'cancel'], { 'state': 'assigned', }) -ShipmentOut() +class ShipmentOutReturn: + __name__ = 'stock.shipment.out.return' -class ShipmentOutReturn(Model): - _name = 'stock.shipment.out.return' - - def _get_inventory_moves(self, incoming_move): + @classmethod + def _get_inventory_moves(cls, incoming_move): result = super(ShipmentOutReturn, - self)._get_inventory_moves(incoming_move) - if result: + cls)._get_inventory_moves(incoming_move) + if result and incoming_move.lot: result['lot'] = incoming_move.lot.id return result - -ShipmentOutReturn()