diff --git a/__init__.py b/__init__.py index 49341b6017..ba6a5024a0 100644 --- a/__init__.py +++ b/__init__.py @@ -1,6 +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 production import * from product import * + + +def register(): + Pool.register( + OrderPoint, + Configuration, + Production, + CreateProductionRequestStart, + Product, + module='stock_supply_production', type_='model') + Pool.register( + CreateProductionRequest, + module='stock_supply_production', type_='wizard') diff --git a/product.py b/product.py index 337708f344..05ff745199 100644 --- a/product.py +++ b/product.py @@ -1,17 +1,17 @@ #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 -from trytond.pool import Pool +from trytond.pool import Pool, PoolMeta + +__all__ = ['Product'] +__metaclass__ = PoolMeta -class Product(Model): - _name = 'product.product' +class Product: + __name__ = 'product.product' - def get_supply_period(self, product): + def get_supply_period(self): 'Return the supply period for the product' pool = Pool() - configuration_obj = pool.get('production.configuration') - return int(configuration_obj.browse(1).supply_period or 0) - -Product() + Configuration = pool.get('production.configuration') + return int(Configuration(1).supply_period or 0) diff --git a/production.py b/production.py index 9d72009e64..0871d1948f 100644 --- a/production.py +++ b/production.py @@ -3,28 +3,31 @@ import datetime from decimal import Decimal -from trytond.model import Model, ModelView, fields -from trytond.pool import Pool +from trytond.model import ModelView, fields +from trytond.pool import Pool, PoolMeta from trytond.transaction import Transaction from trytond.wizard import Wizard, StateView, StateAction, Button +__all__ = ['Configuration', 'Production', + 'CreateProductionRequestStart', 'CreateProductionRequest'] +__metaclass__ = PoolMeta -class Configuration(Model): - _name = 'production.configuration' +class Configuration: + __name__ = 'production.configuration' supply_period = fields.Property(fields.Numeric('Supply Period', digits=(16, 0), help='In number of days', required=True)) - def default_supply_period(self): + @staticmethod + def default_supply_period(): return Decimal(0) -Configuration() +class Production: + __name__ = 'production' -class Production(Model): - _name = 'production' - - def generate_requests(self, clean=True): + @classmethod + def generate_requests(cls, clean=True): """ For each product compute the production request that must be created today to meet product outputs. @@ -32,97 +35,98 @@ class Production(Model): If clean is set, it will remove all previous requests. """ pool = Pool() - order_point_obj = pool.get('stock.order_point') - product_obj = pool.get('product.product') - location_obj = pool.get('stock.location') - date_obj = pool.get('ir.date') - user_obj = pool.get('res.user') - company = user_obj.browse(Transaction().user).company + OrderPoint = pool.get('stock.order_point') + Product = pool.get('product.product') + Location = pool.get('stock.location') + Date = pool.get('ir.date') + User = pool.get('res.user') + company = User(Transaction().user).company if clean: - req_ids = self.search([ + reqs = cls.search([ ('state', '=', 'request'), ]) - self.delete(req_ids) + cls.delete(reqs) # fetch warehouse - warehouse_ids = location_obj.search([ + warehouses = Location.search([ ('type', '=', 'warehouse'), ]) - warehouses = location_obj.browse(warehouse_ids) + warehouse_ids = [w.id for w in warehouses] # fetch order points - order_point_ids = order_point_obj.search([ + order_points = OrderPoint.search([ ('type', '=', 'production'), ]) # index them by product product2ops = {} - for order_point in order_point_obj.browse(order_point_ids): + for order_point in order_points: product2ops[ (order_point.warehouse_location.id, order_point.product.id) ] = order_point # fetch goods - product_ids = product_obj.search([ + products = Product.search([ ('type', '=', 'goods'), ('consumable', '=', False), ('purchasable', '=', False), ]) - products = product_obj.browse(product_ids) # order product by supply period - products_period = sorted([(product_obj.get_supply_period(p), p) - for p in products]) + products_period = sorted([(p.get_supply_period(), p) + for p in products]) # compute requests cursor = Transaction().cursor - today = date_obj.today() + today = Date.today() requests = [] for i in range(0, len(products), cursor.IN_MAX): product_ids = [p.id for p in products[i:i + cursor.IN_MAX]] with Transaction().set_context(forecast=True, stock_date_end=today): - pbl = product_obj.products_by_location(warehouse_ids, + pbl = Product.products_by_location(warehouse_ids, product_ids, with_childs=True, skip_zero=False) for warehouse in warehouses: quantities = dict((x, pbl.pop((warehouse.id, x))) for x in product_ids) - shortages = self.get_shortage(warehouse.id, product_ids, today, + shortages = cls.get_shortage(warehouse.id, product_ids, today, quantities, products_period, product2ops) for product in products[i:i + cursor.IN_MAX]: for date, quantity in shortages[product.id]: - req_values = self.compute_request(product, warehouse, + req = cls.compute_request(product, warehouse, quantity, date, company) - req_id = self.create(req_values) - self.set_moves(self.browse(req_id)) - requests.append(req_id) + req.save() + req.set_moves() + requests.append(req) if requests: - self.generate_requests(clean=False) + cls.generate_requests(clean=False) return requests - def compute_request(self, product, warehouse, quantity, date, company): + @classmethod + def compute_request(cls, product, warehouse, quantity, date, company): """ Return the value of the production request. """ pool = Pool() - date_obj = pool.get('ir.date') - today = date_obj.today() + Date = pool.get('ir.date') + today = Date.today() if date <= today: date = today else: date -= datetime.timedelta(1) - return { - 'planned_date': date, - 'company': company.id, - 'warehouse': warehouse.id, - 'location': warehouse.production_location.id, - 'product': product.id, - 'bom': product.boms[0].bom.id if product.boms else None, - 'uom': product.default_uom.id, - 'quantity': quantity, - 'state': 'request', - } + return cls( + planned_date=date, + company=company, + warehouse=warehouse, + location=warehouse.production_location, + product=product, + bom=product.boms[0].bom if product.boms else None, + uom=product.default_uom, + quantity=quantity, + state='request', + ) - def get_shortage(self, location_id, product_ids, date, quantities, + @classmethod + def get_shortage(cls, location_id, product_ids, date, quantities, products_period, order_points): """ Return for each product a list of dates where the stock quantity is @@ -137,7 +141,7 @@ class Production(Model): order_points is a dictionary that links products to order points. """ pool = Pool() - product_obj = pool.get('product.product') + Product = pool.get('product.product') shortages = {} @@ -170,7 +174,7 @@ class Production(Model): # Update current quantities with Transaction().set_context(stock_date_start=current_date, stock_date_end=current_date): - pbl = product_obj.products_by_location([location_id], + pbl = Product.products_by_location([location_id], product_ids, with_childs=True, skip_zero=False) for key, qty in pbl.iteritems(): _, product_id = key @@ -185,21 +189,15 @@ class Production(Model): return shortages -Production() - class CreateProductionRequestStart(ModelView): 'Create Production Request' - _name = 'production.create_request.start' - _description = __doc__ - -CreateProductionRequestStart() + __name__ = 'production.create_request.start' class CreateProductionRequest(Wizard): 'Create Production Request' - _name = 'production.create_request' - + __name__ = 'production.create_request' start = StateView('production.create_request.start', 'stock_supply_production.production_create_request_start_view_form', [ Button('Cancel', 'end', 'tryton-cancel'), @@ -207,13 +205,11 @@ class CreateProductionRequest(Wizard): ]) create_ = StateAction('production.act_production_request') - def do_create_(self, session, action): + def do_create_(self, action): pool = Pool() - production_obj = pool.get('production') - production_obj.generate_requests() + Production = pool.get('production') + Production.generate_requests() return action, {} - def transition_create_(self, session): + def transition_create_(self): return 'end' - -CreateProductionRequest() diff --git a/stock.py b/stock.py index 6aeba9ea6d..8067b79a61 100644 --- a/stock.py +++ b/stock.py @@ -1,46 +1,39 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. -import copy - -from trytond.model import Model from trytond.pyson import Eval +from trytond.pool import PoolMeta + +__all__ = ['OrderPoint'] +__metaclass__ = PoolMeta -class OrderPoint(Model): - _name = 'stock.order_point' +class OrderPoint: + __name__ = 'stock.order_point' - def __init__(self): - super(OrderPoint, self).__init__() + @classmethod + def __setup__(cls): + super(OrderPoint, cls).__setup__() - self.warehouse_location = copy.copy(self.warehouse_location) - states = copy.copy(self.warehouse_location.states) - states['invisible'] = (states['invisible'] - & (Eval('type') != 'production')) - states['required'] = (states['required'] - | (Eval('type') == 'production')) - self.warehouse_location.states = states + cls.warehouse_location.states['invisible'] &= ( + Eval('type') != 'production') + cls.warehouse_location.states['required'] |= ( + Eval('type') == 'production') option = ('production', 'Production') - if option not in self.type.selection: - self.type = copy.copy(self.type) - self.type.selection = copy.copy(self.type.selection) - self.type.selection.append(option) + if option not in cls.type.selection: + cls.type.selection.append(option) - self._reset_columns() - - def _type2field(self, type=None): + @classmethod + def _type2field(cls, type=None): if type == 'production': return 'warehouse_location' - result = super(OrderPoint, self)._type2field(type=type) + result = super(OrderPoint, cls)._type2field(type=type) if type == None: result['production'] = 'warehouse_location' return result - def get_location(self, ids, name): - locations = super(OrderPoint, self).get_location(ids, name) - for op in self.browse(ids): - if op.type == 'production': - locations[op.id] = op.warehouse_location.id - return locations - -OrderPoint() + def get_location(self, name): + location = super(OrderPoint, self).get_location(name) + if self.type == 'production': + return self.warehouse_location.id + return location