Active Record

This commit is contained in:
Cédric Krier
2012-09-24 22:20:11 +02:00
parent f6406c5762
commit fa2c5338fc
4 changed files with 107 additions and 104 deletions
+14
View File
@@ -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')
+9 -9
View File
@@ -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)
+61 -65
View File
@@ -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()
+23 -30
View File
@@ -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