diff --git a/addons/stock_planning/__init__.py b/addons/stock_planning/__init__.py index f0fea471a21..9bc08bc829c 100644 --- a/addons/stock_planning/__init__.py +++ b/addons/stock_planning/__init__.py @@ -19,6 +19,7 @@ ############################################################################## import stock_planning +import wizard # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock_planning/__openerp__.py b/addons/stock_planning/__openerp__.py index 100e793805b..e09c7d14867 100644 --- a/addons/stock_planning/__openerp__.py +++ b/addons/stock_planning/__openerp__.py @@ -138,7 +138,13 @@ Remarks: - When you wish to work with different periods for some part of products define two kinds of periods (fe. Weekly and Monthly) and use them for different products. Example: If you use always Weekly periods for Products A, and Monthly periods for Products B your all calculations will work correctly. You can also use different kind of periods for the same products from different warehouse or companies. But you cannot use overlapping periods for the same product, warehouse and company because results can be unpredictable. The same apply to Forecasts lines. """, "demo_xml":[], - "update_xml":["security/ir.model.access.csv","stock_planning_view.xml"], + "update_xml": [ + "security/ir.model.access.csv", + "stock_planning_view.xml", + "wizard/stock_planning_create_periods_view.xml", + "wizard/stock_planning_forecast_view.xml", + "wizard/stock_planning_createlines_view.xml", + ], "active": False, "installable": True, } diff --git a/addons/stock_planning/stock_planning.py b/addons/stock_planning/stock_planning.py index 0adae906908..6a8b2893195 100644 --- a/addons/stock_planning/stock_planning.py +++ b/addons/stock_planning/stock_planning.py @@ -35,88 +35,6 @@ 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=None): - cr.execute("select max(date_stop) from stock_period") - 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) - period_start = period_start - RelativeDateTime(hours=period_start.hour, minutes=period_start.minute, seconds=period_start.second) - else: - period_start = mx.DateTime.today() - return period_start.strftime('%Y-%m-%d') - - - _columns = { - 'name': fields.char('Period Name', size=64), - 'date_start': fields.date('Start Date', required=True), - 'date_stop': fields.date('End Date', required=True), - 'period_ids': fields.one2many('stock.period', 'planning_id', 'Periods'), - } - _defaults={ - 'date_start': _get_new_period_start, - } - - def create_period_weekly(self, cr, uid, ids, context=None): - res = self.create_period(cr, uid, ids, context=context) - return { - 'view_type': 'form', - "view_mode": 'tree', - 'res_model': 'stock.period', - 'type': 'ir.actions.act_window', - } - - def create_period_monthly(self, cr, uid, ids, context=None): - interval = context.get('interval',1) - 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: - 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'), - }) - ds = ds + RelativeDateTime(months=interval) - return { - 'view_type': 'form', - "view_mode": 'tree', - 'res_model': 'stock.period', - 'type': 'ir.actions.act_window', - } - - def create_period(self, cr, uid, ids, context=None): - interval = context.get('interval',0) - name = context.get('name','Daily') - 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: - de = ds + RelativeDateTime(days=interval, minutes =-1) - if name =='Daily': - new_name=de.strftime('%Y-%m-%d') - 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'), - 'date_stop': de.strftime('%Y-%m-%d %H:%M:%S'), - }) - ds = ds + RelativeDateTime(days=interval) + 1 - return { - 'view_type': 'form', - "view_mode": 'tree', - 'res_model': 'stock.period', - 'type': 'ir.actions.act_window', - } -stock_period_createlines() - # Periods have no company_id field as they can be shared across similar companies. # If somone thinks different it can be improved. class stock_period(osv.osv): @@ -134,104 +52,6 @@ class stock_period(osv.osv): 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() -# return result and result[0] or False - - - _columns = { - 'company_id': fields.many2one('res.company', 'Company', required=True, select=1), - 'warehouse_id1': fields.many2one('stock.warehouse' , 'Warehouse', required=True, \ - help='Warehouse which forecasts will concern. '\ - 'If during stock planning you will need sales forecast for all warehouses choose any warehouse now.'), - '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."), - } - - _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=None): - product_obj = self.pool.get('product.product') - 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: - raise osv.except_osv(_('Error !'), _('No products in selected category !')) - copy = f.copy_forecast - for p in product_obj.browse(cr, uid, products_ids,{}): - if len(forecast_obj.search(cr, uid, [('product_id','=',p.id) , \ - ('period_id','=',f.period_id1.id), \ - ('user_id','=',uid), \ - ('warehouse_id','=',f.warehouse_id1.id)]))== 0: - forecast_qty = 0.0 -# 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 \ - FROM stock_sale_forecast AS forecast \ - LEFT JOIN stock_period AS period \ - ON forecast.period_id = period.id \ - WHERE (forecast.user_id = %s OR forecast.create_uid = %s OR forecast.write_uid = %s) \ - AND forecast.warehouse_id = %s AND forecast.product_id = %s \ - 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() - if ret: - 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, - '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, - }) - 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'], - } - -stock_sale_forecast_createlines() - - # Stock and Sales Forecast object. Previously stock_planning_sale_prevision. # A lot of changes in 1.1 class stock_sale_forecast(osv.osv): @@ -477,124 +297,6 @@ class stock_sale_forecast(osv.osv): 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 -class stock_planning_createlines(osv.osv_memory): - _name = "stock.planning.createlines" - - 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), - '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', \ - help = 'Planning will be created for products from Product Category selected by this field. '\ - 'This field is ignored when you check \"All Forecasted Product\" box.' ), - 'forecasted_products': fields.boolean('All Products with Forecast', \ - help = "Check this box to create planning for all products having any forecast for selected Warehouse and Period. "\ - "Product Category field will be ignored."), - } - - _defaults = { - '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=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') - for f in self.browse(cr, uid, ids, context=context): - if f.forecasted_products: - cr.execute("SELECT product_id \ - FROM stock_sale_forecast \ - 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)]) - 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 !')) - - for p in product_obj.browse(cr, uid, products_id1,context=context): - if len(planning_obj.search(cr, uid, [('product_id','=',p.id), - ('period_id','=',f.period_id2.id), - ('warehouse_id','=',f.warehouse_id2.id)]))== 0: - cr.execute("SELECT period.date_stop, planning.product_uom, planning.planned_outgoing, planning.to_procure, \ - planning.stock_only, planning.procure_to_stock, planning.confirmed_forecasts_only, \ - planning.supply_warehouse_id, planning.stock_supply_location \ - FROM stock_planning AS planning \ - LEFT JOIN stock_period AS period \ - ON planning.period_id = period.id \ - WHERE (planning.create_uid = %s OR planning.write_uid = %s) \ - AND planning.warehouse_id = %s AND planning.product_id = %s \ - AND period.date_stop < %s \ - ORDER BY period.date_stop DESC", - (uid, uid, f.warehouse_id2.id, p.id, f.period_id2.date_stop) ) - ret=cr.fetchone() -# forecast_qty = ret and ret[0] or 0.0 - 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] - to_procure = ret[3] - stock_only = ret[4] - procure_to_stock = ret[5] - confirmed_forecasts_only = ret[6] - supply_warehouse_id = ret[7] - stock_supply_location = ret[8] - else: - prod_uom = p.uom_id.id - planned_out = False - to_procure = False - stock_only = False - procure_to_stock = False - confirmed_forecasts_only = False - supply_warehouse_id = False - stock_supply_location = False - prod_uos_categ = False - if p.uos_id: - prod_uos_categ = p.uos_id.category_id.id - planning_obj.create(cr, uid, { - 'company_id' : f.warehouse_id2.company_id.id, - 'period_id': f.period_id2.id, - 'warehouse_id' : f.warehouse_id2.id, - 'product_id': p.id, - 'product_uom' : prod_uom, - 'product_uom_categ' : p.uom_id.category_id.id, - 'product_uos_categ' : prod_uos_categ, - 'active_uom' : prod_uom, - 'planned_outgoing': planned_out, - 'to_procure': to_procure, - 'stock_only': stock_only, - 'procure_to_stock': procure_to_stock, - 'confirmed_forecasts_only': confirmed_forecasts_only, - 'supply_warehouse_id': supply_warehouse_id, - 'stock_supply_location': stock_supply_location, - - }) - result = mod_obj._get_id(cr, uid, 'stock_planning', 'view_stock_planning_filter') - id = mod_obj.read(cr, uid, result, ['res_id'], context=context) - return { - 'view_type': 'form', - "view_mode": 'tree', - 'res_model': 'stock.planning', - 'type': 'ir.actions.act_window', - 'search_view_id': id['res_id'], - } -stock_planning_createlines() - - # The main Stock Planning object # A lot of changes by contributor in ver 1.1 class stock_planning(osv.osv): diff --git a/addons/stock_planning/stock_planning_view.xml b/addons/stock_planning/stock_planning_view.xml index d627d68c008..6c98d95c30f 100644 --- a/addons/stock_planning/stock_planning_view.xml +++ b/addons/stock_planning/stock_planning_view.xml @@ -5,42 +5,6 @@ name="Stock and Sales Periods" parent="base.menu_base_config" sequence="20"/> - - - - stock.period.createlines.form - stock.period.createlines - form - -
- - - - - -