[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:
Mustufa Rangwala
2010-07-01 15:58:21 +05:30
parent fc502ff3c4
commit 6a21b5d661
+250 -240
View File
@@ -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