[FIX] stock_planning: Fix for onchange of unsaved records and misc improvements (ref: MTR)
bzr revid: mra@mra-laptop-20100701102821-no3ex2y7h9ka657w
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
||||
# $Id$
|
||||
#
|
||||
@@ -21,16 +21,12 @@
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
import math
|
||||
import mx.DateTime
|
||||
from mx.DateTime import RelativeDateTime, now, DateTime, localtime
|
||||
|
||||
from osv import fields
|
||||
from osv import osv
|
||||
from osv import osv, fields
|
||||
import netsvc
|
||||
|
||||
from tools.translate import _
|
||||
import tools
|
||||
from tools import config
|
||||
|
||||
|
||||
@@ -39,15 +35,14 @@ def rounding(fl, round_value):
|
||||
return fl
|
||||
return round(fl / round_value) * round_value
|
||||
|
||||
|
||||
# Object creating periods quickly
|
||||
# changed that stop_date is created with hour 23:59:00 when it was 00:00:00 stop date was excluded from period
|
||||
class stock_period_createlines(osv.osv_memory):
|
||||
_name = "stock.period.createlines"
|
||||
|
||||
def _get_new_period_start(self,cr,uid,context={}):
|
||||
def _get_new_period_start(self, cr, uid, context=None):
|
||||
cr.execute("select max(date_stop) from stock_period")
|
||||
result=cr.fetchone()
|
||||
result = cr.fetchone()
|
||||
last_date = result and result[0] or False
|
||||
if last_date:
|
||||
period_start = mx.DateTime.strptime(last_date,"%Y-%m-%d %H:%M:%S")+ RelativeDateTime(days=1)
|
||||
@@ -55,7 +50,7 @@ class stock_period_createlines(osv.osv_memory):
|
||||
else:
|
||||
period_start = mx.DateTime.today()
|
||||
return period_start.strftime('%Y-%m-%d')
|
||||
|
||||
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Period Name', size=64),
|
||||
@@ -64,47 +59,47 @@ class stock_period_createlines(osv.osv_memory):
|
||||
'period_ids': fields.one2many('stock.period', 'planning_id', 'Periods'),
|
||||
}
|
||||
_defaults={
|
||||
'date_start':_get_new_period_start,
|
||||
'date_start': _get_new_period_start,
|
||||
}
|
||||
|
||||
def create_period_weekly(self,cr, uid, ids, context={}):
|
||||
res=self.create_period(cr, uid, ids, context, 6, 'Weekly')
|
||||
|
||||
def create_period_weekly(self, cr, uid, ids, context=None):
|
||||
res = self.create_period(cr, uid, ids, context, 6, 'Weekly')
|
||||
return {
|
||||
'view_type': 'form',
|
||||
"view_mode": 'tree',
|
||||
'res_model': 'stock.period',
|
||||
'type': 'ir.actions.act_window',
|
||||
'type': 'ir.actions.act_window',
|
||||
}
|
||||
|
||||
def create_period_monthly(self,cr, uid, ids, context={},interval=1):
|
||||
for p in self.browse(cr, uid, ids, context):
|
||||
|
||||
def create_period_monthly(self,cr, uid, ids, interval=1, context=None):
|
||||
for p in self.browse(cr, uid, ids, context=context):
|
||||
dt = p.date_start
|
||||
ds = mx.DateTime.strptime(p.date_start, '%Y-%m-%d')
|
||||
while ds.strftime('%Y-%m-%d')<p.date_stop:
|
||||
while ds.strftime('%Y-%m-%d') < p.date_stop:
|
||||
de = ds + RelativeDateTime(months=interval, minutes=-1)
|
||||
self.pool.get('stock.period').create(cr, uid, {
|
||||
'name': ds.strftime('%Y/%m'),
|
||||
'date_start': ds.strftime('%Y-%m-%d'),
|
||||
'date_stop': de.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'date_stop': de.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
})
|
||||
ds = ds + RelativeDateTime(months=interval)
|
||||
return {
|
||||
'view_type': 'form',
|
||||
"view_mode": 'tree',
|
||||
'res_model': 'stock.period',
|
||||
'type': 'ir.actions.act_window',
|
||||
}
|
||||
'type': 'ir.actions.act_window',
|
||||
}
|
||||
|
||||
def create_period(self,cr, uid, ids, context={}, interval=0, name='Daily'):
|
||||
for p in self.browse(cr, uid, ids, context):
|
||||
def create_period(self, cr, uid, ids, interval=0, name='Daily', context=None):
|
||||
for p in self.browse(cr, uid, ids, context=context):
|
||||
dt = p.date_start
|
||||
ds = mx.DateTime.strptime(p.date_start, '%Y-%m-%d')
|
||||
while ds.strftime('%Y-%m-%d')<p.date_stop:
|
||||
ds = mx.DateTime.strptime(p.date_start, '%Y-%m-%d')
|
||||
while ds.strftime('%Y-%m-%d') < p.date_stop:
|
||||
de = ds + RelativeDateTime(days=interval, minutes =-1)
|
||||
if name=='Daily':
|
||||
if name =='Daily':
|
||||
new_name=de.strftime('%Y-%m-%d')
|
||||
if name=="Weekly":
|
||||
new_name=de.strftime('%Y, week %W')
|
||||
if name =="Weekly":
|
||||
new_name = de.strftime('%Y, week %W')
|
||||
self.pool.get('stock.period').create(cr, uid, {
|
||||
'name': new_name,
|
||||
'date_start': ds.strftime('%Y-%m-%d'),
|
||||
@@ -115,7 +110,7 @@ class stock_period_createlines(osv.osv_memory):
|
||||
'view_type': 'form',
|
||||
"view_mode": 'tree',
|
||||
'res_model': 'stock.period',
|
||||
'type': 'ir.actions.act_window',
|
||||
'type': 'ir.actions.act_window',
|
||||
}
|
||||
stock_period_createlines()
|
||||
|
||||
@@ -123,29 +118,32 @@ stock_period_createlines()
|
||||
# If somone thinks different it can be improved.
|
||||
class stock_period(osv.osv):
|
||||
_name = "stock.period"
|
||||
_description = "stock period"
|
||||
_columns = {
|
||||
'name': fields.char('Period Name', size=64),
|
||||
'name': fields.char('Period Name', size=64, required=True),
|
||||
'date_start': fields.datetime('Start Date', required=True),
|
||||
'date_stop': fields.datetime('End Date', required=True),
|
||||
'state' : fields.selection([('draft','Draft'),('open','Open'),('close','Close')],'State')
|
||||
'date_stop': fields.datetime('End Date', required=True),
|
||||
'state': fields.selection([('draft','Draft'), ('open','Open'),('close','Close')], 'State')
|
||||
}
|
||||
_defaults = {
|
||||
'state' : lambda * a : 'draft'
|
||||
'state': 'draft'
|
||||
}
|
||||
|
||||
stock_period()
|
||||
|
||||
# Creates forecasts records for products from selected Product Category for selected 'Warehouse - Period'
|
||||
# Object added by contributor in ver 1.1
|
||||
class stock_sale_forecast_createlines(osv.osv_memory):
|
||||
_name = "stock.sale.forecast.createlines"
|
||||
_description = "stock.sale.forecast.createlines"
|
||||
|
||||
# FIXME Add some period sugestion like below
|
||||
|
||||
# def _get_latest_period(self,cr,uid,context={}):
|
||||
# cr.execute("select max(date_stop) from stock_period")
|
||||
# result=cr.fetchone()
|
||||
# result=cr.fetchone()
|
||||
# return result and result[0] or False
|
||||
|
||||
|
||||
|
||||
_columns = {
|
||||
'company_id': fields.many2one('res.company', 'Company', required=True, select=1),
|
||||
@@ -155,25 +153,25 @@ class stock_sale_forecast_createlines(osv.osv_memory):
|
||||
'period_id1': fields.many2one('stock.period' , 'Period', required=True, help = 'Period which forecasts will concern.' ),
|
||||
'product_categ_id1': fields.many2one('product.category' , 'Product Category', required=True, \
|
||||
help ='Product Category of products which created forecasts will concern.'),
|
||||
'copy_forecast' : fields.boolean('Copy Last Forecast', help="Copy quantities from last Stock and Sale Forecast."),
|
||||
'copy_forecast': fields.boolean('Copy Last Forecast', help="Copy quantities from last Stock and Sale Forecast."),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.sale.forecast.createlines', context=c),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.sale.forecast.createlines', context=c),
|
||||
}
|
||||
|
||||
def create_forecast(self,cr, uid, ids, context={}):
|
||||
def create_forecast(self, cr, uid, ids, context=None):
|
||||
product_obj = self.pool.get('product.product')
|
||||
forecast_obj=self.pool.get('stock.sale.forecast')
|
||||
mod_obj =self.pool.get('ir.model.data')
|
||||
for f in self.browse(cr, uid, ids, context):
|
||||
prod_categ_obj=self.pool.get('product.category')
|
||||
template_obj=self.pool.get('product.template')
|
||||
forecast_obj = self.pool.get('stock.sale.forecast')
|
||||
mod_obj = self.pool.get('ir.model.data')
|
||||
prod_categ_obj = self.pool.get('product.category')
|
||||
template_obj = self.pool.get('product.template')
|
||||
for f in self.browse(cr, uid, ids, context=context):
|
||||
categ_ids = f.product_categ_id1.id and [f.product_categ_id1.id] or []
|
||||
prod_categ_ids=prod_categ_obj.search(cr,uid,[('parent_id','child_of',categ_ids)])
|
||||
templates_ids = template_obj.search(cr,uid,[('categ_id','in',prod_categ_ids)])
|
||||
products_ids = product_obj.search(cr,uid,[('product_tmpl_id','in',templates_ids)])
|
||||
if len(products_ids)==0:
|
||||
prod_categ_ids = prod_categ_obj.search(cr, uid, [('parent_id','child_of', categ_ids)])
|
||||
templates_ids = template_obj.search(cr, uid, [('categ_id','in',prod_categ_ids)])
|
||||
products_ids = product_obj.search(cr, uid, [('product_tmpl_id','in',templates_ids)])
|
||||
if len(products_ids) == 0:
|
||||
raise osv.except_osv(_('Error !'), _('No products in selected category !'))
|
||||
copy = f.copy_forecast
|
||||
for p in product_obj.browse(cr, uid, products_ids,{}):
|
||||
@@ -185,7 +183,7 @@ class stock_sale_forecast_createlines(osv.osv_memory):
|
||||
# Not sure if it is expected quantity for this feature (copying forecast from previous period)
|
||||
# because it can take incidental forecast of this warehouse, this product and this user (creating, writing or validating forecast).
|
||||
# It takes only one forecast line (no sum). If user creates only one forecast per period it will be OK. If not I have no idea how to count it.
|
||||
|
||||
|
||||
prod_uom = False
|
||||
if copy:
|
||||
cr.execute("SELECT period.date_stop, forecast.product_qty, forecast.product_uom \
|
||||
@@ -197,35 +195,37 @@ class stock_sale_forecast_createlines(osv.osv_memory):
|
||||
AND period.date_stop < %s \
|
||||
ORDER BY period.date_stop DESC",
|
||||
(uid, uid, uid, f.warehouse_id1.id, p.id, f.period_id1.date_stop) )
|
||||
ret=cr.fetchone()
|
||||
ret = cr.fetchone()
|
||||
if ret:
|
||||
forecast_qty = ret[1]
|
||||
forecast_qty = ret[1]
|
||||
prod_uom = ret[2]
|
||||
prod_uom = prod_uom or p.uom_id.id
|
||||
prod_uos_categ = False
|
||||
if p.uos_id:
|
||||
prod_uos_categ = p.uos_id.category_id.id
|
||||
forecast_obj.create(cr, uid, {
|
||||
'company_id' : f.warehouse_id1.company_id.id,
|
||||
'company_id': f.warehouse_id1.company_id.id,
|
||||
'period_id': f.period_id1.id,
|
||||
'warehouse_id': f.warehouse_id1.id,
|
||||
'product_id': p.id,
|
||||
'product_qty' : forecast_qty,
|
||||
'product_amt' : 0.0,
|
||||
'product_uom' : prod_uom,
|
||||
'active_uom' : prod_uom,
|
||||
'product_uom_categ' : p.uom_id.category_id.id,
|
||||
'product_uos_categ' : prod_uos_categ,
|
||||
'product_qty': forecast_qty,
|
||||
'product_amt': 0.0,
|
||||
'product_uom': prod_uom,
|
||||
'active_uom': prod_uom,
|
||||
'product_uom_categ': p.uom_id.category_id.id,
|
||||
'product_uos_categ': prod_uos_categ,
|
||||
})
|
||||
result = mod_obj._get_id(cr, uid, 'stock_planning', 'view_stock_sale_forecast_filter')
|
||||
id = mod_obj.read(cr, uid, result, ['res_id'], context=context)
|
||||
|
||||
return {
|
||||
'view_type': 'form',
|
||||
"view_mode": 'tree',
|
||||
'res_model': 'stock.sale.forecast',
|
||||
'type': 'ir.actions.act_window',
|
||||
'search_view_id': id['res_id'],
|
||||
'search_view_id': id['res_id'],
|
||||
}
|
||||
|
||||
stock_sale_forecast_createlines()
|
||||
|
||||
|
||||
@@ -233,76 +233,76 @@ stock_sale_forecast_createlines()
|
||||
# A lot of changes in 1.1
|
||||
class stock_sale_forecast(osv.osv):
|
||||
_name = "stock.sale.forecast"
|
||||
|
||||
|
||||
_columns = {
|
||||
'company_id': fields.many2one('res.company', 'Company', required=True),
|
||||
'create_uid': fields.many2one('res.users', 'Responsible'),
|
||||
'name' : fields.char('Name', size=64, readonly=True, states={'draft':[('readonly',False)]}),
|
||||
'company_id':fields.many2one('res.company', 'Company', required=True),
|
||||
'create_uid': fields.many2one('res.users', 'Responsible'),
|
||||
'name': fields.char('Name', size=64, readonly=True, states={'draft': [('readonly',False)]}),
|
||||
'user_id': fields.many2one('res.users' , 'Created/Validated by',readonly=True, \
|
||||
help='Shows who created this forecast, or who validated.'),
|
||||
'warehouse_id': fields.many2one('stock.warehouse' , 'Warehouse', required=True, readonly=True, states={'draft':[('readonly',False)]}, \
|
||||
'warehouse_id': fields.many2one('stock.warehouse' , 'Warehouse', required=True, readonly=True, states={'draft': [('readonly',False)]}, \
|
||||
help='Shows which warehouse this forecast concerns. '\
|
||||
'If during stock planning you will need sales forecast for all warehouses choose any warehouse now.'),
|
||||
'period_id': fields.many2one('stock.period' , 'Period', required=True, readonly=True, states={'draft':[('readonly',False)]}, \
|
||||
help = 'Shows which period this forecast concerns.'),
|
||||
'product_id': fields.many2one('product.product' , 'Product', readonly=True, required=True, states={'draft':[('readonly',False)]}, \
|
||||
help = 'Shows which product this forecast concerns.'),
|
||||
'product_qty' : fields.float('Product Quantity', required=True, readonly=True, states={'draft':[('readonly',False)]}, \
|
||||
'product_qty': fields.float('Product Quantity', required=True, readonly=True, states={'draft':[('readonly',False)]}, \
|
||||
help= 'Forecasted quantity.'),
|
||||
'product_amt' : fields.float('Product Amount', readonly=True, states={'draft':[('readonly',False)]}, \
|
||||
'product_amt': fields.float('Product Amount', readonly=True, states={'draft':[('readonly',False)]}, \
|
||||
help='Forecast value which will be converted to Product Quantity according to prices.'),
|
||||
'product_uom_categ' : fields.many2one('product.uom.categ', 'Product UoM Category'), # Invisible field for product_uom domain
|
||||
'product_uom' : fields.many2one('product.uom', 'Product UoM', required=True, readonly=True, states={'draft':[('readonly',False)]}, \
|
||||
'product_uom_categ': fields.many2one('product.uom.categ', 'Product UoM Category'), # Invisible field for product_uom domain
|
||||
'product_uom': fields.many2one('product.uom', 'Product UoM', required=True, readonly=True, states={'draft':[('readonly',False)]}, \
|
||||
help = "Unit of Measure used to show the quanities of stock calculation." \
|
||||
"You can use units form default category or from second category (UoS category)."),
|
||||
'product_uos_categ' : fields.many2one('product.uom.categ', 'Product UoS Category'), # Invisible field for product_uos domain
|
||||
# Field used in onchange_uom to check what uom was before change and recalculate quantities acording to old uom (active_uom) and new uom.
|
||||
'active_uom' :fields.many2one('product.uom', string = "Active UoM"),
|
||||
'state' : fields.selection([('draft','Draft'),('validated','Validated')],'State',readonly=True),
|
||||
'analyzed_period1_id' : fields.many2one('stock.period' , 'Period1', readonly=True, states={'draft':[('readonly',False)]},),
|
||||
'analyzed_period2_id' : fields.many2one('stock.period' , 'Period2', readonly=True, states={'draft':[('readonly',False)]},),
|
||||
'analyzed_period3_id' : fields.many2one('stock.period' , 'Period3', readonly=True, states={'draft':[('readonly',False)]},),
|
||||
'analyzed_period4_id' : fields.many2one('stock.period' , 'Period4', readonly=True, states={'draft':[('readonly',False)]},),
|
||||
'analyzed_period5_id' : fields.many2one('stock.period' , 'Period5', readonly=True, states={'draft':[('readonly',False)]},),
|
||||
'analyzed_user_id' : fields.many2one('res.users' , 'This User', required=False, readonly=True, states={'draft':[('readonly',False)]},),
|
||||
'analyzed_dept_id' : fields.many2one('hr.department' , 'This Department', required=False, \
|
||||
'active_uom': fields.many2one('product.uom', string = "Active UoM"),
|
||||
'state': fields.selection([('draft','Draft'),('validated','Validated')],'State',readonly=True),
|
||||
'analyzed_period1_id': fields.many2one('stock.period' , 'Period1', readonly=True, states={'draft':[('readonly',False)]},),
|
||||
'analyzed_period2_id': fields.many2one('stock.period' , 'Period2', readonly=True, states={'draft':[('readonly',False)]},),
|
||||
'analyzed_period3_id': fields.many2one('stock.period' , 'Period3', readonly=True, states={'draft':[('readonly',False)]},),
|
||||
'analyzed_period4_id': fields.many2one('stock.period' , 'Period4', readonly=True, states={'draft':[('readonly',False)]},),
|
||||
'analyzed_period5_id': fields.many2one('stock.period' , 'Period5', readonly=True, states={'draft':[('readonly',False)]},),
|
||||
'analyzed_user_id': fields.many2one('res.users' , 'This User', required=False, readonly=True, states={'draft':[('readonly',False)]},),
|
||||
'analyzed_dept_id': fields.many2one('hr.department' , 'This Department', required=False, \
|
||||
readonly=True, states={'draft':[('readonly',False)]},),
|
||||
'analyzed_warehouse_id' : fields.many2one('stock.warehouse' , 'This Warehouse', required=False, \
|
||||
'analyzed_warehouse_id': fields.many2one('stock.warehouse' , 'This Warehouse', required=False, \
|
||||
readonly=True, states={'draft':[('readonly',False)]}),
|
||||
'analyze_company' : fields.boolean('Per Company', readonly=True, states={'draft':[('readonly',False)]}, \
|
||||
'analyze_company': fields.boolean('Per Company', readonly=True, states={'draft':[('readonly',False)]}, \
|
||||
help = "Check this box to see the sales for whole company."),
|
||||
'analyzed_period1_per_user' : fields.float('This User Period1', readonly=True),
|
||||
'analyzed_period2_per_user' : fields.float('This User Period2', readonly=True),
|
||||
'analyzed_period3_per_user' : fields.float('This User Period3', readonly=True),
|
||||
'analyzed_period4_per_user' : fields.float('This User Period4', readonly=True),
|
||||
'analyzed_period5_per_user' : fields.float('This User Period5', readonly=True),
|
||||
'analyzed_period1_per_dept' : fields.float('This Dept Period1', readonly=True),
|
||||
'analyzed_period2_per_dept' : fields.float('This Dept Period2', readonly=True),
|
||||
'analyzed_period3_per_dept' : fields.float('This Dept Period3', readonly=True),
|
||||
'analyzed_period4_per_dept' : fields.float('This Dept Period4', readonly=True),
|
||||
'analyzed_period5_per_dept' : fields.float('This Dept Period5', readonly=True),
|
||||
'analyzed_period1_per_warehouse' : fields.float('This Warehouse Period1', readonly=True),
|
||||
'analyzed_period2_per_warehouse' : fields.float('This Warehouse Period2', readonly=True),
|
||||
'analyzed_period3_per_warehouse' : fields.float('This Warehouse Period3', readonly=True),
|
||||
'analyzed_period4_per_warehouse' : fields.float('This Warehouse Period4', readonly=True),
|
||||
'analyzed_period5_per_warehouse' : fields.float('This Warehouse Period5', readonly=True),
|
||||
'analyzed_period1_per_company' : fields.float('This Copmany Period1', readonly=True),
|
||||
'analyzed_period2_per_company' : fields.float('This Company Period2', readonly=True),
|
||||
'analyzed_period3_per_company' : fields.float('This Company Period3', readonly=True),
|
||||
'analyzed_period4_per_company' : fields.float('This Company Period4', readonly=True),
|
||||
'analyzed_period5_per_company' : fields.float('This Company Period5', readonly=True),
|
||||
'analyzed_period1_per_user': fields.float('This User Period1', readonly=True),
|
||||
'analyzed_period2_per_user': fields.float('This User Period2', readonly=True),
|
||||
'analyzed_period3_per_user': fields.float('This User Period3', readonly=True),
|
||||
'analyzed_period4_per_user': fields.float('This User Period4', readonly=True),
|
||||
'analyzed_period5_per_user': fields.float('This User Period5', readonly=True),
|
||||
'analyzed_period1_per_dept': fields.float('This Dept Period1', readonly=True),
|
||||
'analyzed_period2_per_dept': fields.float('This Dept Period2', readonly=True),
|
||||
'analyzed_period3_per_dept': fields.float('This Dept Period3', readonly=True),
|
||||
'analyzed_period4_per_dept': fields.float('This Dept Period4', readonly=True),
|
||||
'analyzed_period5_per_dept': fields.float('This Dept Period5', readonly=True),
|
||||
'analyzed_period1_per_warehouse': fields.float('This Warehouse Period1', readonly=True),
|
||||
'analyzed_period2_per_warehouse': fields.float('This Warehouse Period2', readonly=True),
|
||||
'analyzed_period3_per_warehouse': fields.float('This Warehouse Period3', readonly=True),
|
||||
'analyzed_period4_per_warehouse': fields.float('This Warehouse Period4', readonly=True),
|
||||
'analyzed_period5_per_warehouse': fields.float('This Warehouse Period5', readonly=True),
|
||||
'analyzed_period1_per_company': fields.float('This Copmany Period1', readonly=True),
|
||||
'analyzed_period2_per_company': fields.float('This Company Period2', readonly=True),
|
||||
'analyzed_period3_per_company': fields.float('This Company Period3', readonly=True),
|
||||
'analyzed_period4_per_company': fields.float('This Company Period4', readonly=True),
|
||||
'analyzed_period5_per_company': fields.float('This Company Period5', readonly=True),
|
||||
}
|
||||
_defaults = {
|
||||
'user_id': lambda obj, cr, uid, context: uid,
|
||||
'state': lambda *args: 'draft',
|
||||
'state': 'draft',
|
||||
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.sale.forecast', context=c),
|
||||
}
|
||||
|
||||
def action_validate(self, cr, uid, ids, *args):
|
||||
self.write(cr, uid, ids, {'state':'validated','user_id':uid})
|
||||
return True
|
||||
|
||||
def unlink(self, cr, uid, ids, context={}):
|
||||
|
||||
def unlink(self, cr, uid, ids, context=None):
|
||||
forecasts = self.read(cr, uid, ids, ['state'])
|
||||
unlink_ids = []
|
||||
for t in forecasts:
|
||||
@@ -313,17 +313,18 @@ class stock_sale_forecast(osv.osv):
|
||||
osv.osv.unlink(self, cr, uid, unlink_ids,context=context)
|
||||
return True
|
||||
|
||||
def onchange_company(self, cr, uid, ids, company_id):
|
||||
def onchange_company(self, cr, uid, ids, company_id=False):
|
||||
result = {}
|
||||
if company_id:
|
||||
result['warehouse_id'] = False
|
||||
result['analyzed_user_id'] = False
|
||||
result['analyzed_dept_id'] = False
|
||||
result['analyzed_warehouse_id'] = False
|
||||
if not company_id:
|
||||
return result
|
||||
result['warehouse_id'] = False
|
||||
result['analyzed_user_id'] = False
|
||||
result['analyzed_dept_id'] = False
|
||||
result['analyzed_warehouse_id'] = False
|
||||
return {'value': result}
|
||||
|
||||
def product_id_change(self, cr, uid, ids, product_id):
|
||||
ret={}
|
||||
def product_id_change(self, cr, uid, ids, product_id=False):
|
||||
ret = {}
|
||||
if product_id:
|
||||
product_rec = self.pool.get('product.product').browse(cr, uid, product_id)
|
||||
ret['product_uom'] = product_rec.uom_id.id
|
||||
@@ -337,19 +338,24 @@ class stock_sale_forecast(osv.osv):
|
||||
res = {'value': ret}
|
||||
return res
|
||||
|
||||
def onchange_uom(self, cr, uid, ids, product_uom=False, product_qty=0.0, active_uom=False ):
|
||||
ret={}
|
||||
val1 = self.browse(cr, uid, ids)
|
||||
val = val1[0]
|
||||
coeff_uom2def = self._to_default_uom_factor(cr, uid, val, active_uom, {})
|
||||
coeff_def2uom, round_value = self._from_default_uom_factor( cr, uid, val, product_uom, {})
|
||||
coeff = coeff_uom2def * coeff_def2uom
|
||||
ret['product_qty'] = rounding(coeff * product_qty, round_value)
|
||||
ret['active_uom'] = product_uom
|
||||
def onchange_uom(self, cr, uid, ids, product_uom=False, product_qty=0.0, active_uom=False):
|
||||
ret = {}
|
||||
if not ids:
|
||||
return {}
|
||||
if product_uom:
|
||||
val1 = self.browse(cr, uid, ids)
|
||||
val = val1[0]
|
||||
coeff_uom2def = self._to_default_uom_factor(cr, uid, val, active_uom, {})
|
||||
coeff_def2uom, round_value = self._from_default_uom_factor( cr, uid, val, product_uom, {})
|
||||
coeff = coeff_uom2def * coeff_def2uom
|
||||
ret['product_qty'] = rounding(coeff * product_qty, round_value)
|
||||
ret['active_uom'] = product_uom
|
||||
return {'value': ret}
|
||||
|
||||
def product_amt_change(self, cr, uid, ids, product_amt = 0.0, product_uom=False):
|
||||
ret={}
|
||||
ret = {}
|
||||
if not ids:
|
||||
return {}
|
||||
round_value = 1
|
||||
if product_amt:
|
||||
coeff_def2uom = 1
|
||||
@@ -361,7 +367,7 @@ class stock_sale_forecast(osv.osv):
|
||||
res = {'value': ret}
|
||||
return res
|
||||
|
||||
def _to_default_uom_factor(self, cr, uid, val, uom_id, context):
|
||||
def _to_default_uom_factor(self, cr, uid, val, uom_id, context=None):
|
||||
uom_obj = self.pool.get('product.uom')
|
||||
uom = uom_obj.browse(cr, uid, uom_id, context=context)
|
||||
coef = uom.factor
|
||||
@@ -378,32 +384,31 @@ class stock_sale_forecast(osv.osv):
|
||||
return res / val.product_id.uom_id.factor, uom.rounding
|
||||
|
||||
def _sales_per_users(self, cr, uid, so, so_line, company, users):
|
||||
|
||||
cr.execute("SELECT sum(sol.product_uom_qty) FROM sale_order_line AS sol LEFT JOIN sale_order AS s ON (s.id = sol.order_id) " \
|
||||
"WHERE (sol.id IN %s) AND (s.state NOT IN (\'draft\',\'cancel\')) AND (s.id IN %s) AND (s.company_id=%s) " \
|
||||
"AND (s.user_id IN %s) " ,(tuple(so_line), tuple(so), company, tuple(users)))
|
||||
ret = cr.fetchone()[0] or 0.0
|
||||
return ret
|
||||
|
||||
def _sales_per_warehouse(self, cr, uid, so, so_line, company, shops):
|
||||
def _sales_per_warehouse(self, cr, uid, so, so_line, company, shops):
|
||||
cr.execute("SELECT sum(sol.product_uom_qty) FROM sale_order_line AS sol LEFT JOIN sale_order AS s ON (s.id = sol.order_id) " \
|
||||
"WHERE (sol.id IN %s) AND (s.state NOT IN (\'draft\',\'cancel\')) AND (s.id IN %s)AND (s.company_id=%s) " \
|
||||
"AND (s.shop_id IN %s)" ,(tuple(so_line), tuple(so), company, tuple(shops)))
|
||||
ret = cr.fetchone()[0] or 0.0
|
||||
return ret
|
||||
|
||||
def _sales_per_company(self, cr, uid, so, so_line, company, ):
|
||||
def _sales_per_company(self, cr, uid, so, so_line, company):
|
||||
cr.execute("SELECT sum(sol.product_uom_qty) FROM sale_order_line AS sol LEFT JOIN sale_order AS s ON (s.id = sol.order_id) " \
|
||||
"WHERE (sol.id IN %s) AND (s.state NOT IN (\'draft\',\'cancel\')) AND (s.id IN %s) AND (s.company_id=%s)"%(tuple(so_line), tuple(so), company))
|
||||
"WHERE (sol.id IN %s) AND (s.state NOT IN (\'draft\',\'cancel\')) AND (s.id IN %s) AND (s.company_id=%s)", (tuple(so_line), tuple(so), company))
|
||||
ret = cr.fetchone()[0] or 0.0
|
||||
return ret
|
||||
|
||||
|
||||
def calculate_sales_history(self, cr, uid, ids, context, *args):
|
||||
sales=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],]
|
||||
for obj in self.browse(cr, uid, ids):
|
||||
periods =obj.analyzed_period1_id, obj.analyzed_period2_id, obj.analyzed_period3_id, obj.analyzed_period4_id, obj.analyzed_period5_id
|
||||
sales = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],]
|
||||
for obj in self.browse(cr, uid, ids):
|
||||
periods = obj.analyzed_period1_id, obj.analyzed_period2_id, obj.analyzed_period3_id, obj.analyzed_period4_id, obj.analyzed_period5_id
|
||||
so_obj = self.pool.get('sale.order')
|
||||
so_line_obj= self.pool.get('sale.order.line')
|
||||
so_line_obj = self.pool.get('sale.order.line')
|
||||
so_line_product_ids = so_line_obj.search(cr, uid, [('product_id','=', obj.product_id.id)], context = context)
|
||||
if so_line_product_ids:
|
||||
so_line_product_set = ','.join(map(str,so_line_product_ids))
|
||||
@@ -430,58 +435,58 @@ class stock_sale_forecast(osv.osv):
|
||||
# so_period_set = ','.join(map(str,so_period_ids))
|
||||
if obj.analyzed_user_id:
|
||||
user_set = str(obj.analyzed_user_id.id)
|
||||
|
||||
sales[i][0] =self._sales_per_users(cr, uid, so_period_ids, so_line_product_ids, obj.company_id.id, user_set)
|
||||
sales[i][0] *=factor
|
||||
|
||||
sales[i][0] = self._sales_per_users(cr, uid, so_period_ids, so_line_product_ids, obj.company_id.id, user_set)
|
||||
sales[i][0] *= factor
|
||||
if dept_users:
|
||||
sales[i][1]= self._sales_per_users(cr, uid, so_period_ids, so_line_product_ids, obj.company_id.id, dept_users_set)
|
||||
sales[i][1]*=factor
|
||||
sales[i][1] = self._sales_per_users(cr, uid, so_period_ids, so_line_product_ids, obj.company_id.id, dept_users_set)
|
||||
sales[i][1] *= factor
|
||||
if shops:
|
||||
sales[i][2]= self._sales_per_warehouse(cr, uid, so_period_ids, so_line_product_ids, obj.company_id.id, shops_set)
|
||||
sales[i][2]*=factor
|
||||
sales[i][2] = self._sales_per_warehouse(cr, uid, so_period_ids, so_line_product_ids, obj.company_id.id, shops_set)
|
||||
sales[i][2] *= factor
|
||||
if obj.analyze_company:
|
||||
sales[i][3]= self._sales_per_company(cr, uid, so_period_ids, so_line_product_ids, obj.company_id.id, )
|
||||
sales[i][3]*=factor
|
||||
sales[i][3] = self._sales_per_company(cr, uid, so_period_ids, so_line_product_ids, obj.company_id.id, )
|
||||
sales[i][3] *= factor
|
||||
self.write(cr, uid, ids, {
|
||||
'analyzed_period1_per_user':sales[0][0],
|
||||
'analyzed_period2_per_user':sales[1][0],
|
||||
'analyzed_period3_per_user':sales[2][0],
|
||||
'analyzed_period4_per_user':sales[3][0],
|
||||
'analyzed_period5_per_user':sales[4][0],
|
||||
'analyzed_period1_per_dept':sales[0][1],
|
||||
'analyzed_period2_per_dept':sales[1][1],
|
||||
'analyzed_period3_per_dept':sales[2][1],
|
||||
'analyzed_period4_per_dept':sales[3][1],
|
||||
'analyzed_period5_per_dept':sales[4][1],
|
||||
'analyzed_period1_per_warehouse':sales[0][2],
|
||||
'analyzed_period2_per_warehouse':sales[1][2],
|
||||
'analyzed_period3_per_warehouse':sales[2][2],
|
||||
'analyzed_period4_per_warehouse':sales[3][2],
|
||||
'analyzed_period5_per_warehouse':sales[4][2],
|
||||
'analyzed_period1_per_company':sales[0][3],
|
||||
'analyzed_period2_per_company':sales[1][3],
|
||||
'analyzed_period3_per_company':sales[2][3],
|
||||
'analyzed_period4_per_company':sales[3][3],
|
||||
'analyzed_period5_per_company':sales[4][3],
|
||||
'analyzed_period1_per_user': sales[0][0],
|
||||
'analyzed_period2_per_user': sales[1][0],
|
||||
'analyzed_period3_per_user': sales[2][0],
|
||||
'analyzed_period4_per_user': sales[3][0],
|
||||
'analyzed_period5_per_user': sales[4][0],
|
||||
'analyzed_period1_per_dept': sales[0][1],
|
||||
'analyzed_period2_per_dept': sales[1][1],
|
||||
'analyzed_period3_per_dept': sales[2][1],
|
||||
'analyzed_period4_per_dept': sales[3][1],
|
||||
'analyzed_period5_per_dept': sales[4][1],
|
||||
'analyzed_period1_per_warehouse': sales[0][2],
|
||||
'analyzed_period2_per_warehouse': sales[1][2],
|
||||
'analyzed_period3_per_warehouse': sales[2][2],
|
||||
'analyzed_period4_per_warehouse': sales[3][2],
|
||||
'analyzed_period5_per_warehouse': sales[4][2],
|
||||
'analyzed_period1_per_company': sales[0][3],
|
||||
'analyzed_period2_per_company': sales[1][3],
|
||||
'analyzed_period3_per_company': sales[2][3],
|
||||
'analyzed_period4_per_company': sales[3][3],
|
||||
'analyzed_period5_per_company': sales[4][3],
|
||||
})
|
||||
return True
|
||||
|
||||
|
||||
stock_sale_forecast()
|
||||
|
||||
# Creates stock planning records for products from selected Product Category for selected 'Warehouse - Period'
|
||||
# Object added by contributor in ver 1.1
|
||||
# Creates stock planning records for products from selected Product Category for selected 'Warehouse - Period'
|
||||
# Object added by contributor in ver 1.1
|
||||
class stock_planning_createlines(osv.osv_memory):
|
||||
_name = "stock.planning.createlines"
|
||||
|
||||
def onchange_company(self, cr, uid, ids, company_id):
|
||||
def onchange_company(self, cr, uid, ids, company_id=False):
|
||||
result = {}
|
||||
if company_id:
|
||||
result['warehouse_id2'] = False
|
||||
return {'value': result}
|
||||
|
||||
_columns = {
|
||||
'company_id': fields.many2one('res.company', 'Company', required = True),
|
||||
'company_id': fields.many2one('res.company', 'Company', required=True),
|
||||
'period_id2': fields.many2one('stock.period' , 'Period', required=True, help = 'Period which planning will concern.'),
|
||||
'warehouse_id2': fields.many2one('stock.warehouse' , 'Warehouse', required=True, help = 'Warehouse which planning will concern.'),
|
||||
'product_categ_id2': fields.many2one('product.category' , 'Product Category', \
|
||||
@@ -493,13 +498,15 @@ class stock_planning_createlines(osv.osv_memory):
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.planning', context=c),
|
||||
'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.planning', context=c),
|
||||
}
|
||||
|
||||
def create_planning(self,cr, uid, ids, context={}):
|
||||
def create_planning(self,cr, uid, ids, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
product_obj = self.pool.get('product.product')
|
||||
planning_obj=self.pool.get('stock.planning')
|
||||
mod_obj =self.pool.get('ir.model.data')
|
||||
planning_obj = self.pool.get('stock.planning')
|
||||
mod_obj = self.pool.get('ir.model.data')
|
||||
for f in self.browse(cr, uid, ids, context=context):
|
||||
if f.forecasted_products:
|
||||
cr.execute("SELECT product_id \
|
||||
@@ -507,11 +514,11 @@ class stock_planning_createlines(osv.osv_memory):
|
||||
WHERE (period_id = %s) AND (warehouse_id = %s)", (f.period_id2.id, f.warehouse_id2.id))
|
||||
products_id1 = [x for x, in cr.fetchall()]
|
||||
else:
|
||||
prod_categ_obj=self.pool.get('product.category')
|
||||
template_obj=self.pool.get('product.template')
|
||||
categ_ids = f.product_categ_id2.id and [f.product_categ_id2.id] or []
|
||||
prod_categ_ids=prod_categ_obj.search(cr,uid,[('parent_id','child_of',categ_ids)])
|
||||
templates_ids = template_obj.search(cr,uid,[('categ_id','in',prod_categ_ids)])
|
||||
prod_categ_obj = self.pool.get('product.category')
|
||||
template_obj = self.pool.get('product.template')
|
||||
categ_ids = f.product_categ_id2.id and [f.product_categ_id2.id] or []
|
||||
prod_categ_ids = prod_categ_obj.search(cr,uid,[('parent_id','child_of',categ_ids)])
|
||||
templates_ids = template_obj.search(cr,uid,[('categ_id','in',prod_categ_ids)])
|
||||
products_id1 = product_obj.search(cr,uid,[('product_tmpl_id','in',templates_ids)])
|
||||
if len(products_id1)==0:
|
||||
raise osv.except_osv(_('Error !'), _('No forecasts for selected period or no products in selected category !'))
|
||||
@@ -536,7 +543,7 @@ class stock_planning_createlines(osv.osv_memory):
|
||||
if ret:
|
||||
# raise osv.except_osv(_('Error !'), _('ret is %s %s %s %s %s %s')%(ret[0],ret[2],ret[3],ret[4],ret[5],ret[6],))
|
||||
prod_uom = ret[1]
|
||||
planned_out = ret[2]
|
||||
planned_out = ret[2]
|
||||
to_procure = ret[3]
|
||||
stock_only = ret[4]
|
||||
procure_to_stock = ret[5]
|
||||
@@ -545,7 +552,7 @@ class stock_planning_createlines(osv.osv_memory):
|
||||
stock_supply_location = ret[8]
|
||||
else:
|
||||
prod_uom = p.uom_id.id
|
||||
planned_out = False
|
||||
planned_out = False
|
||||
to_procure = False
|
||||
stock_only = False
|
||||
procure_to_stock = False
|
||||
@@ -564,7 +571,7 @@ class stock_planning_createlines(osv.osv_memory):
|
||||
'product_uom_categ' : p.uom_id.category_id.id,
|
||||
'product_uos_categ' : prod_uos_categ,
|
||||
'active_uom' : prod_uom,
|
||||
'planned_outgoing': planned_out,
|
||||
'planned_outgoing': planned_out,
|
||||
'to_procure': to_procure,
|
||||
'stock_only': stock_only,
|
||||
'procure_to_stock': procure_to_stock,
|
||||
@@ -579,8 +586,8 @@ class stock_planning_createlines(osv.osv_memory):
|
||||
'view_type': 'form',
|
||||
"view_mode": 'tree',
|
||||
'res_model': 'stock.planning',
|
||||
'type': 'ir.actions.act_window',
|
||||
'search_view_id': id['res_id'],
|
||||
'type': 'ir.actions.act_window',
|
||||
'search_view_id': id['res_id'],
|
||||
}
|
||||
stock_planning_createlines()
|
||||
|
||||
@@ -589,11 +596,12 @@ stock_planning_createlines()
|
||||
# A lot of changes by contributor in ver 1.1
|
||||
class stock_planning(osv.osv):
|
||||
_name = "stock.planning"
|
||||
|
||||
def _get_in_out(self, cr, uid, val, date_start, date_stop, direction, done, context):
|
||||
|
||||
def _get_in_out(self, cr, uid, val, date_start, date_stop, direction, done, context=None):
|
||||
# res = {}
|
||||
# if not context:
|
||||
# context = {}
|
||||
if not context:
|
||||
context = {}
|
||||
product_obj = self.pool.get('product.product')
|
||||
mapping = {'in': {
|
||||
'field': "incoming_qty",
|
||||
'adapter': lambda x: x,
|
||||
@@ -610,22 +618,21 @@ class stock_planning(osv.osv):
|
||||
locations.extend([val.warehouse_id.lot_input_id.id, val.warehouse_id.lot_output_id.id])
|
||||
context['location'] = locations
|
||||
context['compute_child'] = True
|
||||
product_obj = self.pool.get('product.product')
|
||||
prod_id = val.product_id.id
|
||||
if done:
|
||||
c1=context.copy()
|
||||
c1 = context.copy()
|
||||
c1.update({ 'states':('done',), 'what':(direction,) })
|
||||
prod_ids = [prod_id]
|
||||
st = product_obj.get_product_available(cr,uid, prod_ids, context=c1)
|
||||
res = mapping[direction]['adapter'](st.get(prod_id,0.0))
|
||||
else:
|
||||
product=product_obj.read(cr, uid, prod_id,[], context)
|
||||
product = product_obj.read(cr, uid, prod_id,[], context)
|
||||
product_qty = product[mapping[direction]['field']]
|
||||
res = mapping[direction]['adapter'](product_qty)
|
||||
# res[val.id] = product_obj['incoming_qty']
|
||||
return res
|
||||
|
||||
def _get_outgoing_before(self, cr, uid, val, date_start, date_stop, context):
|
||||
def _get_outgoing_before(self, cr, uid, val, date_start, date_stop, context=None):
|
||||
cr.execute("SELECT sum(planning.planned_outgoing), planning.product_uom \
|
||||
FROM stock_planning AS planning \
|
||||
LEFT JOIN stock_period AS period \
|
||||
@@ -648,12 +655,12 @@ class stock_planning(osv.osv):
|
||||
coef = coef * res_coef
|
||||
res_qty += rounding(qty * coef, round_value)
|
||||
return res_qty
|
||||
|
||||
|
||||
def _get_forecast(self, cr, uid, ids, field_names, arg, context):
|
||||
|
||||
def _get_forecast(self, cr, uid, ids, field_names, arg, context=None):
|
||||
res = {}
|
||||
for val in self.browse(cr, uid, ids):
|
||||
res[val.id]={}
|
||||
res[val.id] = {}
|
||||
valid_part = val.confirmed_forecasts_only and " AND state = 'validated'" or ""
|
||||
cr.execute('SELECT sum(product_qty), product_uom \
|
||||
FROM stock_sale_forecast \
|
||||
@@ -673,7 +680,7 @@ class stock_planning(osv.osv):
|
||||
res[val.id]['warehouse_forecast'] = rounding(res[val.id]['warehouse_forecast'], val.product_id.uom_id.rounding)
|
||||
return res
|
||||
|
||||
def _get_stock_start(self, cr, uid, val, date, context):
|
||||
def _get_stock_start(self, cr, uid, val, date, context=None):
|
||||
context['from_date'] = None
|
||||
context['to_date'] = date
|
||||
locations = [val.warehouse_id.lot_stock_id.id,]
|
||||
@@ -684,7 +691,7 @@ class stock_planning(osv.osv):
|
||||
product_obj = self.pool.get('product.product').read(cr, uid,val.product_id.id,[], context)
|
||||
res = product_obj['qty_available'] # value for stock_start
|
||||
return res
|
||||
|
||||
|
||||
def _get_past_future(self, cr, uid, ids, field_names, arg, context):
|
||||
res = {}
|
||||
for val in self.browse(cr, uid, ids, context=context):
|
||||
@@ -694,14 +701,14 @@ class stock_planning(osv.osv):
|
||||
res[val.id] = 'Future'
|
||||
return res
|
||||
|
||||
def _get_op(self, cr, uid, ids, field_names, arg, context): # op = OrderPoint
|
||||
def _get_op(self, cr, uid, ids, field_names, arg, context=None): # op = OrderPoint
|
||||
res = {}
|
||||
for val in self.browse(cr, uid, ids, context=context):
|
||||
res[val.id]={}
|
||||
cr.execute("SELECT product_min_qty, product_max_qty, product_uom \
|
||||
FROM stock_warehouse_orderpoint \
|
||||
WHERE warehouse_id = %s AND product_id = %s AND active = 'TRUE'", (val.warehouse_id.id, val.product_id.id))
|
||||
ret = cr.fetchone() or [0.0,0.0,False]
|
||||
ret = cr.fetchone() or [0.0,0.0,False]
|
||||
coef = 1
|
||||
round_value = 1
|
||||
if ret[2]:
|
||||
@@ -711,42 +718,45 @@ class stock_planning(osv.osv):
|
||||
res[val.id]['minimum_op'] = rounding(ret[0]*coef, round_value)
|
||||
res[val.id]['maximum_op'] = ret[1]*coef
|
||||
return res
|
||||
|
||||
def onchange_company(self, cr, uid, ids, company_id):
|
||||
|
||||
def onchange_company(self, cr, uid, ids, company_id=False):
|
||||
result = {}
|
||||
if company_id:
|
||||
result['warehouse_id'] = False
|
||||
return {'value': result}
|
||||
|
||||
def onchange_uom(self, cr, uid, ids, product_uom, ):
|
||||
def onchange_uom(self, cr, uid, ids, product_uom=False):
|
||||
ret = {}
|
||||
if not product_uom:
|
||||
return {}
|
||||
ret={}
|
||||
if not ids:
|
||||
return {}
|
||||
val1 = self.browse(cr, uid, ids)
|
||||
val = val1[0]
|
||||
coeff_uom2def = self._to_default_uom_factor(cr, uid, val, val.active_uom.id, {})
|
||||
coeff_def2uom, round_value = self._from_default_uom_factor( cr, uid, val, product_uom, {})
|
||||
coeff = coeff_uom2def * coeff_def2uom
|
||||
ret['planned_outgoing'] = rounding(coeff * val.planned_outgoing, round_value)
|
||||
ret['to_procure'] = rounding(coeff * val.to_procure, round_value)
|
||||
if val.active_uom:
|
||||
coeff_uom2def = self._to_default_uom_factor(cr, uid, val, val.active_uom.id, {})
|
||||
coeff_def2uom, round_value = self._from_default_uom_factor( cr, uid, val, product_uom, {})
|
||||
coeff = coeff_uom2def * coeff_def2uom
|
||||
ret['planned_outgoing'] = rounding(coeff * val.planned_outgoing, round_value)
|
||||
ret['to_procure'] = rounding(coeff * val.to_procure, round_value)
|
||||
ret['active_uom'] = product_uom
|
||||
return {'value': ret}
|
||||
|
||||
_columns = {
|
||||
'company_id': fields.many2one('res.company', 'Company', required = True),
|
||||
'history' : fields.text('Procurement History', readonly=True, help = "History of procurement or internal supply of this planning line."),
|
||||
'history': fields.text('Procurement History', readonly=True, help = "History of procurement or internal supply of this planning line."),
|
||||
'state' : fields.selection([('draft','Draft'),('done','Done')],'State',readonly=True),
|
||||
'period_id': fields.many2one('stock.period' , 'Period', required=True, \
|
||||
help = 'Period for this planning. Requisition will be created for beginning of the period.'),
|
||||
'warehouse_id' : fields.many2one('stock.warehouse','Warehouse', required=True),
|
||||
'warehouse_id': fields.many2one('stock.warehouse','Warehouse', required=True),
|
||||
'product_id': fields.many2one('product.product' , 'Product', required=True, help = 'Product which this planning is created for.'),
|
||||
'product_uom_categ' : fields.many2one('product.uom.categ', 'Product UoM Category'), # Invisible field for product_uom domain
|
||||
'product_uom' : fields.many2one('product.uom', 'UoM', required=True, help = "Unit of Measure used to show the quanities of stock calculation." \
|
||||
'product_uom': fields.many2one('product.uom', 'UoM', required=True, help = "Unit of Measure used to show the quanities of stock calculation." \
|
||||
"You can use units form default category or from second category (UoS category)."),
|
||||
'product_uos_categ' : fields.many2one('product.uom.categ', 'Product UoM Category'), # Invisible field for product_uos domain
|
||||
'product_uos_categ': fields.many2one('product.uom.categ', 'Product UoM Category'), # Invisible field for product_uos domain
|
||||
# Field used in onchange_uom to check what uom was before change to recalculate quantities acording to old uom (active_uom) and new uom.
|
||||
'active_uom' :fields.many2one('product.uom', string = "Active UoM"),
|
||||
'planned_outgoing' : fields.float('Planned Out', required=True, \
|
||||
'active_uom': fields.many2one('product.uom', string = "Active UoM"),
|
||||
'planned_outgoing': fields.float('Planned Out', required=True, \
|
||||
help = 'Enter planned outgoing quantity from selected Warehouse during the selected Period of selected Product. '\
|
||||
'To plan this value look at Confirmed Out or Sales Forecasts. This value should be equal or greater than Confirmed Out.'),
|
||||
'company_forecast': fields.function(_get_forecast, method=True, string ='Company Forecast', multi = 'company', \
|
||||
@@ -770,54 +780,54 @@ class stock_planning(osv.osv):
|
||||
'to_procure': fields.float(string='Planned In', required=True, \
|
||||
help = 'Enter quantity which (by your plan) should come in. Change this value and observe Stock simulation. ' \
|
||||
'This value should be equal or greater than Confirmed In.'),
|
||||
'line_time' : fields.function(_get_past_future, method=True,type='char', string='Past/Future'),
|
||||
'minimum_op' : fields.function(_get_op, method=True, type='float', string = 'Minimum Rule', multi= 'minimum', \
|
||||
'line_time': fields.function(_get_past_future, method=True,type='char', string='Past/Future'),
|
||||
'minimum_op': fields.function(_get_op, method=True, type='float', string = 'Minimum Rule', multi= 'minimum', \
|
||||
help = 'Minimum quantity set in Minimum Stock Rules for this Warhouse'),
|
||||
'maximum_op' : fields.function(_get_op, method=True, type='float', string = 'Maximum Rule', multi= 'maximum', \
|
||||
'maximum_op': fields.function(_get_op, method=True, type='float', string = 'Maximum Rule', multi= 'maximum', \
|
||||
help = 'Maximum quantity set in Minimum Stock Rules for this Warhouse'),
|
||||
'outgoing_before' : fields.float('Planned Out Before', readonly=True, \
|
||||
'outgoing_before': fields.float('Planned Out Before', readonly=True, \
|
||||
help= 'Planned Out in periods before calculated. '\
|
||||
'Between start date of current period and one day before start of calculated period.'),
|
||||
'incoming_before': fields.float('Incoming Before', readonly = True, \
|
||||
help= 'Confirmed incoming in periods before calculated (Including Already In). '\
|
||||
'Between start date of current period and one day before start of calculated period.'),
|
||||
'stock_start' : fields.float('Initial Stock', readonly=True, \
|
||||
'stock_start': fields.float('Initial Stock', readonly=True, \
|
||||
help= 'Stock quantity one day before current period.'),
|
||||
'already_out' : fields.float('Already Out', readonly=True, \
|
||||
'already_out': fields.float('Already Out', readonly=True, \
|
||||
help= 'Quantity which is already dispatched out of this warehouse in current period.'),
|
||||
'already_in' : fields.float('Already In', readonly=True, \
|
||||
'already_in': fields.float('Already In', readonly=True, \
|
||||
help= 'Quantity which is already picked up to this warehouse in current period.'),
|
||||
'stock_only' : fields.boolean("Stock Location Only", help = "Check to calculate stock location of selected warehouse only. " \
|
||||
'stock_only': fields.boolean("Stock Location Only", help = "Check to calculate stock location of selected warehouse only. " \
|
||||
"If not selected calculation is made for input, stock and output location of warehouse."),
|
||||
"procure_to_stock" : fields.boolean("Procure To Stock Location", help = "Chect to make procurement to stock location of selected warehouse. " \
|
||||
"procure_to_stock": fields.boolean("Procure To Stock Location", help = "Chect to make procurement to stock location of selected warehouse. " \
|
||||
"If not selected procurement will be made into input location of warehouse."),
|
||||
"confirmed_forecasts_only" : fields.boolean("Validated Forecasts", help = "Check to take validated forecasts only. " \
|
||||
"confirmed_forecasts_only": fields.boolean("Validated Forecasts", help = "Check to take validated forecasts only. " \
|
||||
"If not checked system takes validated and draft forecasts."),
|
||||
'supply_warehouse_id' : fields.many2one('stock.warehouse','Source Warehouse', help = "Warehouse used as source in supply pick move created by 'Supply from Another Warhouse'."),
|
||||
"stock_supply_location" : fields.boolean("Stock Supply Location", help = "Check to supply from Stock location of Supply Warehouse. " \
|
||||
'supply_warehouse_id': fields.many2one('stock.warehouse','Source Warehouse', help = "Warehouse used as source in supply pick move created by 'Supply from Another Warhouse'."),
|
||||
"stock_supply_location": fields.boolean("Stock Supply Location", help = "Check to supply from Stock location of Supply Warehouse. " \
|
||||
"If not checked supply will be made from Output location of Supply Warehouse. Used in 'Supply from Another Warhouse' with Supply Warehouse."),
|
||||
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'state': lambda *args: 'draft' ,
|
||||
'to_procure' : 0.0,
|
||||
'planned_outgoing' : 0.0,
|
||||
'to_procure': 0.0,
|
||||
'planned_outgoing': 0.0,
|
||||
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.planning', context=c),
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_order = 'period_id'
|
||||
|
||||
def _to_default_uom_factor(self, cr, uid, val, uom_id, context):
|
||||
def _to_default_uom_factor(self, cr, uid, val, uom_id, context=None):
|
||||
uom_obj = self.pool.get('product.uom')
|
||||
uom = uom_obj.browse(cr, uid, uom_id, context=context)
|
||||
coef = uom.factor
|
||||
coef = uom.factor
|
||||
if uom.category_id.id != val.product_id.uom_id.category_id.id:
|
||||
coef = coef / val.product_id.uos_coeff
|
||||
return val.product_id.uom_id.factor / coef
|
||||
|
||||
|
||||
def _from_default_uom_factor(self, cr, uid, val, uom_id, context):
|
||||
def _from_default_uom_factor(self, cr, uid, val, uom_id, context=None):
|
||||
uom_obj = self.pool.get('product.uom')
|
||||
uom = uom_obj.browse(cr, uid, uom_id, context=context)
|
||||
res = uom.factor
|
||||
@@ -828,7 +838,7 @@ class stock_planning(osv.osv):
|
||||
def calculate_planning(self, cr, uid, ids, context, *args):
|
||||
one_minute = RelativeDateTime(minutes=1)
|
||||
current_date_beginning_c = mx.DateTime.today()
|
||||
current_date_end_c = current_date_beginning_c + RelativeDateTime(days=1, minutes=-1) # to get hour 23:59:00
|
||||
current_date_end_c = current_date_beginning_c + RelativeDateTime(days=1, minutes=-1) # to get hour 23:59:00
|
||||
current_date_beginning = current_date_beginning_c.strftime('%Y-%m-%d %H:%M:%S')
|
||||
current_date_end = current_date_end_c.strftime('%Y-%m-%d %H:%M:%S')
|
||||
for val in self.browse(cr, uid, ids, context=context):
|
||||
@@ -855,9 +865,9 @@ class stock_planning(osv.osv):
|
||||
incoming_before = self._get_in_out(cr, uid, val, start_date_current_period, day_before_calculated_period, direction='in', done = False, context=context),
|
||||
stock_start = self._get_stock_start(cr, uid, val, date_for_start, context=context),
|
||||
if start_date_current_period == val.period_id.date_start: # current period is calculated
|
||||
current=True
|
||||
current = True
|
||||
else:
|
||||
current=False
|
||||
current = False
|
||||
factor, round_value = self._from_default_uom_factor(cr, uid, val, val.product_uom.id, context=context)
|
||||
self.write(cr, uid, ids, {
|
||||
'already_out': rounding(already_out[0]*factor,round_value),
|
||||
@@ -868,16 +878,16 @@ class stock_planning(osv.osv):
|
||||
'incoming_before': rounding((incoming_before[0]+ (not current and already_in[0]))*factor,round_value),
|
||||
'outgoing_left': rounding(val.planned_outgoing - (outgoing[0] + (current and already_out[0]))*factor,round_value),
|
||||
'incoming_left': rounding(val.to_procure - (incoming[0] + (current and already_in[0]))*factor,round_value),
|
||||
'stock_start' : rounding(stock_start[0]*factor,round_value),
|
||||
'stock_start': rounding(stock_start[0]*factor,round_value),
|
||||
'stock_simulation': rounding(val.to_procure - val.planned_outgoing + (stock_start[0]+ incoming_before[0] - outgoing_before[0] \
|
||||
+ (not current and already_in[0]))*factor,round_value),
|
||||
})
|
||||
return True
|
||||
|
||||
# method below converts quantities and uoms to general OpenERP standard with UoM Qty, UoM, UoS Qty, UoS.
|
||||
# from stock_planning standard where you have one Qty and one UoM (any from UoM or UoS category)
|
||||
# from stock_planning standard where you have one Qty and one UoM (any from UoM or UoS category)
|
||||
# so if UoM is from UoM category it is used as UoM in standard and if product has UoS the UoS will be calcualated.
|
||||
# If UoM is from UoS category it is recalculated to basic UoS from product (in planning you can use any UoS from UoS category)
|
||||
# If UoM is from UoS category it is recalculated to basic UoS from product (in planning you can use any UoS from UoS category)
|
||||
# and basic UoM is calculated.
|
||||
def _qty_to_standard(self, cr, uid, val, context):
|
||||
uos = False
|
||||
@@ -899,7 +909,7 @@ class stock_planning(osv.osv):
|
||||
coeff_def2uom, round_value = self._from_default_uom_factor(cr, uid, val, uom, {})
|
||||
uom_qty = rounding(val.incoming_left * coeff_uom2def * coeff_def2uom, round_value)
|
||||
return uom_qty, uom, uos_qty, uos
|
||||
|
||||
|
||||
def procure_incomming_left(self, cr, uid, ids, context, *args):
|
||||
for obj in self.browse(cr, uid, ids):
|
||||
if obj.incoming_left <= 0:
|
||||
@@ -916,7 +926,7 @@ class stock_planning(osv.osv):
|
||||
'product_uom': uom,
|
||||
'product_uos_qty': uos_qty,
|
||||
'product_uos': uos,
|
||||
'location_id': obj.procure_to_stock and obj.warehouse_id.lot_stock_id.id or obj.warehouse_id.lot_input_id.id,
|
||||
'location_id': obj.procure_to_stock and obj.warehouse_id.lot_stock_id.id or obj.warehouse_id.lot_input_id.id,
|
||||
'procure_method': 'make_to_order',
|
||||
'note' : _("Procurement created in MPS by user: ") + str(user.login) + _(" Creation Date: ") + \
|
||||
time.strftime('%Y-%m-%d %H:%M:%S') + \
|
||||
@@ -956,7 +966,7 @@ class stock_planning(osv.osv):
|
||||
'origin': _('MPS(') + str(user.login) +') '+ obj.period_id.name,
|
||||
'type': 'internal',
|
||||
'state': 'auto',
|
||||
'date' : obj.period_id.date_start,
|
||||
'date' : obj.period_id.date_start,
|
||||
'move_type': 'direct',
|
||||
'invoice_state': 'none',
|
||||
'company_id': obj.company_id.id,
|
||||
@@ -1002,9 +1012,9 @@ class stock_planning(osv.osv):
|
||||
})
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def product_id_change(self, cr, uid, ids, product_id):
|
||||
ret={}
|
||||
ret = {}
|
||||
if product_id:
|
||||
product_rec = self.pool.get('product.product').browse(cr, uid, product_id)
|
||||
ret['product_uom'] = product_rec.uom_id.id
|
||||
|
||||
Reference in New Issue
Block a user