diff --git a/addons/base_module_record/wizard/base_module_record_data.py b/addons/base_module_record/wizard/base_module_record_data.py
index fa9c8a6826e..d8554e0cbdb 100644
--- a/addons/base_module_record/wizard/base_module_record_data.py
+++ b/addons/base_module_record/wizard/base_module_record_data.py
@@ -96,6 +96,8 @@ def _record_objects(self, cr, uid, data, context):
if '_auto' in dir(obj_pool):
if not obj_pool._auto:
continue
+ elif '_log_access' not in dir(obj_pool):
+ search_condition = []
search_ids=obj_pool.search(cr,uid,search_condition)
for s_id in search_ids:
args=(cr.dbname,uid,obj_name,'copy',s_id,{},context)
diff --git a/addons/base_report_creator/base_report_creator.py b/addons/base_report_creator/base_report_creator.py
index 773458fe3cb..a026a077c85 100644
--- a/addons/base_report_creator/base_report_creator.py
+++ b/addons/base_report_creator/base_report_creator.py
@@ -23,33 +23,15 @@ from osv import fields, osv
from tools.translate import _
from tools import ustr
-class report_creator(osv.osv):
+class report_result(osv.osv):
"""
Report Creator
"""
- _name = "base_report_creator.report"
+ _name = "base_report_creator_report.result"
_description = "Report"
- model_set_id = False
#
# Should request only used fields
#
- def export_data(self, cr, uid, ids, fields_to_export, context=None):
- if context is None:
- context = {}
- data_l = self.read(cr, uid, ids, ['sql_query'], context=context)
- final_datas = []
- #start Loop
- for record in data_l:
- datas = []
- for key in fields_to_export:
- value = record.get(key,'')
- if isinstance(value, tuple):
- datas.append(ustr(value[1]))
- else:
- datas.append(ustr(value))
- final_datas += [datas]
- #End Loop
- return {'datas': final_datas}
def fields_get(self, cr, user, fields=None, context=None):
"""
@@ -64,9 +46,9 @@ class report_creator(osv.osv):
data = context and context.get('report_id', False) or False
if (not context) or 'report_id' not in context:
- return super(report_creator, self).fields_get(cr, user, fields, context)
+ return super(report_result, self).fields_get(cr, user, fields, context)
if data:
- report = self.browse(cr, user, data)
+ report = self.pool.get('base_report_creator.report').browse(cr, user, data,context=context)
models = {}
#Start Loop
for model in report.model_ids:
@@ -80,12 +62,8 @@ class report_creator(osv.osv):
i += 1
else:
fields['column_count'] = {'readonly': True, 'type': 'integer', 'string': 'Count', 'size': 64, 'name': 'column_count'}
-
return fields
- #
- # Should Call self.fields_get !
- #
def fields_view_get(self, cr, user, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
"""
Overrides orm field_view_get.
@@ -98,8 +76,8 @@ class report_creator(osv.osv):
data = context and context.get('report_id', False) or False
if (not context) or 'report_id' not in context:
- return super(report_creator, self).fields_view_get(cr, user, view_id, view_type, context, toolbar=toolbar, submenu=submenu)
- report = self.browse(cr, user, data)
+ return super(report_result, self).fields_view_get(cr, user, view_id, view_type, context, toolbar=toolbar, submenu=submenu)
+ report = self.pool.get('base_report_creator.report').browse(cr, user, context.get('report_id'), context=context)
models = {}
for model in report.model_ids:
models[model.model] = self.pool.get(model.model).fields_get(cr, user, context=context)
@@ -192,31 +170,11 @@ class report_creator(osv.osv):
"""
if context is None:
context = {}
- data = context.get('report_id', False)
- res = super(report_creator, self).read(cr, user, ids, fields, context, load)
- if (not context) or 'report_id' not in context:
- return res
- wp = ''
- for data in res:
- if not data.get('sql_query'):
- return res
- if self.model_set_id:
- wp = [self._id_get(cr, user, data, context) + (' in (%s)' % (','.join(map(lambda x: "'" + str(x) + "'", ids))))]
- cr.execute(data['sql_query'])
- res = cr.dictfetchall()
- fields_get = self.fields_get(cr, user, None, context)
- for r in res:
- for k in r:
- r[k] = r[k] or False
- field_dict = fields_get.get(k)
- field_type = field_dict and field_dict.get('type', False) or False
- if field_type and field_type == 'many2one':
- if r[k] == False:
- continue
- related_name = self.pool.get(field_dict.get('relation')).name_get(cr, user, [r[k]], context)[0]
- r[k] = related_name
-
- return res
+ report_id = context.get('active_id', False)
+ report = self.pool.get('base_report_creator.report').browse(cr, user, context.get('report_id'), context=context)
+ cr.execute(report.sql_query)
+ result = cr.dictfetchall()
+ return result
def search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False):
"""
@@ -231,9 +189,9 @@ class report_creator(osv.osv):
context_id = context.get('report_id', False)
if (not context) or 'report_id' not in context:
- return super(report_creator, self).search(cr, user, args, offset, limit, order, context, count)
+ return {}
if context_id:
- report = self.browse(cr, user, context_id)
+ report = self.pool.get('base_report_creator.report').browse(cr, user, context_id, context=context)
i = 0
fields = {}
for f in report.field_ids:
@@ -254,10 +212,42 @@ class report_creator(osv.osv):
ctx = context or {}
ctx['getid'] = True
sql_query = report.sql_query
- cr.execute(sql_query, newargs2)
+ cr.execute(sql_query) # TODO: FILTER
result = cr.fetchall()
return map(lambda x: x[0], result)
+report_result()
+
+
+class report_creator(osv.osv):
+ """
+ Report Creator
+ """
+ _name = "base_report_creator.report"
+ _description = "Report"
+ model_set_id = False
+ #
+ # Should request only used fields
+ #
+ def export_data(self, cr, uid, ids, fields_to_export, context=None):
+ if context is None:
+ context = {}
+ data_l = self.read(cr, uid, ids, ['sql_query'], context=context)
+ final_datas = []
+ #start Loop
+ for record in data_l:
+ datas = []
+ for key in fields_to_export:
+ value = record.get(key,'')
+ if isinstance(value, tuple):
+ datas.append(ustr(value[1]))
+ else:
+ datas.append(ustr(value))
+ final_datas += [datas]
+ #End Loop
+ return {'datas': final_datas}
+
+
def _path_get(self, cr, uid, models, filter_ids=[]):
"""
@param cr: the current row, from the database cursor,
@@ -465,7 +455,7 @@ class report_creator(osv.osv):
'name': rep.name,
'view_type': 'form',
'view_mode': view_mode,
- 'res_model': 'base_report_creator.report',
+ 'res_model': 'base_report_creator_report.result',
'type': 'ir.actions.act_window',
'context': "{'report_id':%d}" % (rep.id,),
'nodestroy': True,
@@ -596,3 +586,4 @@ class report_creator_filter(osv.osv):
}
report_creator_filter()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+
diff --git a/addons/crm/__openerp__.py b/addons/crm/__openerp__.py
index 169b300d86a..db69144b408 100644
--- a/addons/crm/__openerp__.py
+++ b/addons/crm/__openerp__.py
@@ -41,7 +41,7 @@ appropriate staff, and make sure all future correspondence gets to the right
place.
The CRM module has a email gateway for the synchronisation interface
-between mails and OpenERP.
+between mails and OpenERP.
Create dashboard for CRM that includes:
* My Leads (list)
* Leads by Stage (graph)
@@ -95,6 +95,7 @@ Create dashboard for CRM that includes:
'crm_meeting_view.xml',
'crm_meeting_menu.xml',
+ 'crm_meeting_shortcut_data.xml',
'crm_phonecall_view.xml',
'crm_phonecall_menu.xml',
@@ -106,12 +107,12 @@ Create dashboard for CRM that includes:
'report/crm_phonecall_report_view.xml',
'process/crm_configuration_process.xml',
- 'crm_installer_view.xml',
-
+ 'crm_installer_view.xml',
+
'res_partner_view.xml',
'board_crm_view.xml',
'board_crm_statistical_view.xml',
-
+
],
'demo_xml': [
'crm_demo.xml',
diff --git a/addons/crm/crm_meeting_menu.xml b/addons/crm/crm_meeting_menu.xml
index a75528810e0..35ff86cb5b8 100644
--- a/addons/crm/crm_meeting_menu.xml
+++ b/addons/crm/crm_meeting_menu.xml
@@ -92,12 +92,6 @@
action="crm_case_categ_meet" parent="menu_meeting_sale"
sequence="1" />
-
- Meetings
- ir.ui.menu
-
-
-
Meeting Invitations
ir.actions.act_window
diff --git a/addons/crm/crm_meeting_shortcut_data.xml b/addons/crm/crm_meeting_shortcut_data.xml
new file mode 100644
index 00000000000..fcba36f7a61
--- /dev/null
+++ b/addons/crm/crm_meeting_shortcut_data.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+ Meetings
+ ir.ui.menu
+
+
+
+
+
+
diff --git a/addons/mrp/mrp.py b/addons/mrp/mrp.py
index 39793316591..3c1125df8b3 100644
--- a/addons/mrp/mrp.py
+++ b/addons/mrp/mrp.py
@@ -342,7 +342,7 @@ class mrp_bom(osv.osv):
if context is None:
context = {}
bom_data = self.read(cr, uid, id, [], context=context)
- default.update({'name': bom_data['name'] + ' ' + _('Copy')})
+ default.update({'name': bom_data['name'] + ' ' + _('Copy'), 'bom_id':False})
return super(mrp_bom, self).copy_data(cr, uid, id, default, context=context)
mrp_bom()
@@ -444,7 +444,7 @@ class mrp_production(osv.osv):
'bom_id': fields.many2one('mrp.bom', 'Bill of Material', domain=[('bom_id','=',False)]),
'routing_id': fields.many2one('mrp.routing', string='Routing', on_delete='set null', help="The list of operations (list of work centers) to produce the finished product. The routing is mainly used to compute work center costs during operations and to plan future loads on work centers based on production plannification."),
- 'picking_id': fields.many2one('stock.picking', 'Picking list', readonly=True,
+ 'picking_id': fields.many2one('stock.picking', 'Picking list', readonly=True, ondelete="restrict",
help="This is the internal picking list that brings the finished product to the production plan"),
'move_prod_id': fields.many2one('stock.move', 'Move product', readonly=True),
'move_lines': fields.many2many('stock.move', 'mrp_production_move_ids', 'production_id', 'move_id', 'Products to Consume', domain=[('state','not in', ('done', 'cancel'))], states={'done':[('readonly',True)]}),
@@ -602,12 +602,18 @@ class mrp_production(osv.osv):
workcenter_line_obj.create(cr, uid, line)
return len(results)
- def action_cancel(self, cr, uid, ids):
+ def action_cancel(self, cr, uid, ids, context=None):
""" Cancels the production order and related stock moves.
@return: True
"""
+ if context is None:
+ context = {}
move_obj = self.pool.get('stock.move')
- for production in self.browse(cr, uid, ids):
+ for production in self.browse(cr, uid, ids, context=context):
+ if production.state == 'confirmed' and production.picking_id.state not in ('draft', 'cancel'):
+ raise osv.except_osv(
+ _('Could not cancel manufacturing order !'),
+ _('You must first cancel related internal picking attached to this manufacturing order.'))
if production.move_created_ids:
move_obj.action_cancel(cr, uid, [x.id for x in production.move_created_ids])
move_obj.action_cancel(cr, uid, [x.id for x in production.move_lines])
@@ -664,7 +670,7 @@ class mrp_production(osv.osv):
"""
stock_mov_obj = self.pool.get('stock.move')
production = self.browse(cr, uid, production_id, context=context)
-
+
final_product_todo = []
produced_qty = 0
@@ -708,9 +714,9 @@ class mrp_production(osv.osv):
if production_mode == 'consume_produce':
# To produce remaining qty of final product
vals = {'state':'confirmed'}
- final_product_todo = [x.id for x in production.move_created_ids]
+ #final_product_todo = [x.id for x in production.move_created_ids]
#stock_mov_obj.write(cr, uid, final_product_todo, vals)
- stock_mov_obj.action_confirm(cr, uid, final_product_todo, context)
+ #stock_mov_obj.action_confirm(cr, uid, final_product_todo, context)
produced_products = {}
for produced_product in production.move_created_ids2:
if produced_product.scrapped:
diff --git a/addons/mrp/mrp_view.xml b/addons/mrp/mrp_view.xml
index 3b2fdae8ab1..52a3dc6aca4 100644
--- a/addons/mrp/mrp_view.xml
+++ b/addons/mrp/mrp_view.xml
@@ -343,6 +343,54 @@
+
@@ -412,6 +460,28 @@
+
+ mrp.bom.component.tree
+ mrp.bom
+ tree
+ child_complete_ids
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Bill of Materials
ir.actions.act_window
@@ -426,6 +496,7 @@
ir.actions.act_window
mrp.bom
form
+
[('bom_id','!=',False)]
Bills of materials components are components and sub-products used to create master bills of materials. Use this menu to search in which BoM a specific component is used.
@@ -616,7 +687,6 @@
-
@@ -630,7 +700,8 @@
-
+
+
@@ -645,7 +716,6 @@
-
+ colspan="2" />
-
+
@@ -101,7 +101,7 @@
-
+
@@ -567,7 +567,7 @@
-
+
@@ -635,12 +635,6 @@
form
-
- Products
- ir.ui.menu
-
-
-
diff --git a/addons/product/report/product_pricelist.py b/addons/product/report/product_pricelist.py
index 1148718668b..7e9748c2523 100644
--- a/addons/product/report/product_pricelist.py
+++ b/addons/product/report/product_pricelist.py
@@ -62,18 +62,18 @@ class product_pricelist(report_sxw.rml_parse):
def _get_pricelist(self, pricelist_id):
pool = pooler.get_pool(self.cr.dbname)
- pricelist = pool.get('product.pricelist').read(self.cr, self.uid, [pricelist_id], ['name'])[0]
+ pricelist = pool.get('product.pricelist').read(self.cr, self.uid, [pricelist_id], ['name'], context=self.localcontext)[0]
return pricelist['name']
def _get_currency(self, pricelist_id):
pool = pooler.get_pool(self.cr.dbname)
- pricelist = pool.get('product.pricelist').read(self.cr, self.uid, [pricelist_id], ['currency_id'])[0]
+ pricelist = pool.get('product.pricelist').read(self.cr, self.uid, [pricelist_id], ['currency_id'], context=self.localcontext)[0]
return pricelist['currency_id'][1]
def _get_currency_symbol(self, pricelist_id):
pool = pooler.get_pool(self.cr.dbname)
- pricelist = pool.get('product.pricelist').read(self.cr, self.uid, [pricelist_id], ['currency_id'])[0]
- symbol = pool.get('res.currency').read(self.cr, self.uid, [pricelist['currency_id'][0]], ['symbol'])[0]
+ pricelist = pool.get('product.pricelist').read(self.cr, self.uid, [pricelist_id], ['currency_id'], context=self.localcontext)[0]
+ symbol = pool.get('res.currency').read(self.cr, self.uid, [pricelist['currency_id'][0]], ['symbol'], context=self.localcontext)[0]
return symbol['symbol'] or ''
def _get_categories(self, products,form):
@@ -88,13 +88,13 @@ class product_pricelist(report_sxw.rml_parse):
if product.categ_id.id not in cat_ids:
cat_ids.append(product.categ_id.id)
- cats = pool.get('product.category').name_get(self.cr, self.uid, cat_ids)
+ cats = pool.get('product.category').name_get(self.cr, self.uid, cat_ids, context=self.localcontext)
if not cats:
return res
for cat in cats:
- product_ids=pool.get('product.product').search(self.cr, self.uid, [('id','in',pro_ids),('categ_id','=',cat[0])])
+ product_ids=pool.get('product.product').search(self.cr, self.uid, [('id', 'in', pro_ids), ('categ_id', '=', cat[0])], context=self.localcontext)
products = []
- for product in pool.get('product.product').read(self.cr, self.uid, product_ids, ['name','code']):
+ for product in pool.get('product.product').read(self.cr, self.uid, product_ids, ['name', 'code'], context=self.localcontext):
val = {
'id':product['id'],
'name':product['name'],
@@ -114,7 +114,7 @@ class product_pricelist(report_sxw.rml_parse):
def _get_price(self,pricelist_id, product_id,qty):
sale_price_digits = self.get_digits(dp='Sale Price')
pool = pooler.get_pool(self.cr.dbname)
- price_dict = pool.get('product.pricelist').price_get(self.cr, self.uid, [pricelist_id], product_id,qty)
+ price_dict = pool.get('product.pricelist').price_get(self.cr, self.uid, [pricelist_id], product_id, qty, context=self.localcontext)
if price_dict[pricelist_id]:
price = self.formatLang(price_dict[pricelist_id], digits=sale_price_digits)
else:
diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py
index d2c0c0238e4..1c5e8cff492 100644
--- a/addons/purchase/purchase.py
+++ b/addons/purchase/purchase.py
@@ -148,7 +148,7 @@ class purchase_order(osv.osv):
STATE_SELECTION = [
('draft', 'Request for Quotation'),
('wait', 'Waiting'),
- ('confirmed', 'Waiting Supplier Ack'),
+ ('confirmed', 'Waiting Approval'),
('approved', 'Approved'),
('except_picking', 'Shipping Exception'),
('except_invoice', 'Invoice Exception'),
@@ -455,6 +455,7 @@ class purchase_order(osv.osv):
'state': 'draft',
'purchase_line_id': order_line.id,
'company_id': order.company_id.id,
+ 'price_unit': order_line.price_unit
})
if order_line.move_dest_id:
self.pool.get('stock.move').write(cr, uid, [order_line.move_dest_id.id], {'location_id':order.location_id.id})
@@ -816,4 +817,22 @@ class procurement_order(osv.osv):
procurement_order()
+class stock_invoice_onshipping(osv.osv_memory):
+ _inherit = "stock.invoice.onshipping"
+
+ def create_invoice(self, cr, uid, ids, context=None):
+ if context is None:
+ context = {}
+ res = super(stock_invoice_onshipping,self).create_invoice(cr, uid, ids, context=context)
+ purchase_obj = self.pool.get('purchase.order')
+ picking_obj = self.pool.get('stock.picking')
+ for pick_id in res:
+ pick = picking_obj.browse(cr, uid, pick_id, context=context)
+ if pick.purchase_id:
+ purchase_obj.write(cr, uid, [pick.purchase_id.id], {
+ 'invoice_ids': [(4, res[pick_id])]}, context=context)
+ return res
+
+stock_invoice_onshipping()
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/purchase/purchase_demo.xml b/addons/purchase/purchase_demo.xml
index 57c06eab346..f3f0ef0672c 100644
--- a/addons/purchase/purchase_demo.xml
+++ b/addons/purchase/purchase_demo.xml
@@ -5,19 +5,19 @@
-
+
-
+
-
+
@@ -48,7 +48,7 @@
[PC3] Medium PC
-
+
900
1
diff --git a/addons/purchase/purchase_view.xml b/addons/purchase/purchase_view.xml
index 359810fb306..7ee96dca850 100644
--- a/addons/purchase/purchase_view.xml
+++ b/addons/purchase/purchase_view.xml
@@ -15,7 +15,7 @@
-
+
@@ -32,7 +32,7 @@
-
+
@@ -40,7 +40,7 @@
-
+
@@ -113,10 +113,10 @@
-
+
-
+
@@ -194,7 +194,7 @@
-
+
@@ -292,7 +292,7 @@
You can create a request for quotation when you want to buy products to a supplier but the purchase is not confirmed yet. Use also this menu to review requests for quotation created automatically based on your logistic rules (minimum stock, MTO, etc). You can convert the request for quotation into a purchase order once the order is confirmed. If you use the extended interface (from user's preferences), you can select the way to control your supplier invoices: based on the order, based on the receptions or manual encoding.
-
@@ -458,7 +458,7 @@
Purchase Lines Not Invoiced
ir.actions.act_window
purchase.order.line
- [('state','in',('confirmed','done')), ('invoiced', '=', False)]
+ [('order_id.invoice_method','<>','picking'), ('state','in',('confirmed','done')), ('invoiced', '=', False)]
form
tree,form
diff --git a/addons/purchase/report/purchase_report_view.xml b/addons/purchase/report/purchase_report_view.xml
index 7f52ca73cf0..40c05e2955c 100644
--- a/addons/purchase/report/purchase_report_view.xml
+++ b/addons/purchase/report/purchase_report_view.xml
@@ -171,7 +171,8 @@
-
+
diff --git a/addons/purchase/stock.py b/addons/purchase/stock.py
index 0d82baa96aa..e32528f985d 100644
--- a/addons/purchase/stock.py
+++ b/addons/purchase/stock.py
@@ -58,6 +58,19 @@ class stock_picking(osv.osv):
'purchase_id': False,
}
+ def _get_address_invoice(self, cr, uid, picking):
+ """ Gets invoice address of a partner
+ @return {'contact': address, 'invoice': address} for invoice
+ """
+ res = super(stock_picking, self)._get_address_invoice(cr, uid, picking)
+ if picking.purchase_id:
+ partner_obj = self.pool.get('res.partner')
+ partner = picking.purchase_id.partner_id or picking.address_id.partner_id
+ data = partner_obj.address_get(cr, uid, [partner.id],
+ ['contact', 'invoice'])
+ res.update(data)
+ return res
+
def get_currency_id(self, cursor, user, picking):
if picking.purchase_id:
return picking.purchase_id.pricelist_id.currency_id.id
diff --git a/addons/purchase_requisition/purchase_requisition_view.xml b/addons/purchase_requisition/purchase_requisition_view.xml
index c9580357e57..c68c6dbbb89 100644
--- a/addons/purchase_requisition/purchase_requisition_view.xml
+++ b/addons/purchase_requisition/purchase_requisition_view.xml
@@ -22,7 +22,7 @@
-
+
diff --git a/addons/purchase_requisition/security/ir.model.access.csv b/addons/purchase_requisition/security/ir.model.access.csv
index 4e14688ecc5..ec8c031f88b 100644
--- a/addons/purchase_requisition/security/ir.model.access.csv
+++ b/addons/purchase_requisition/security/ir.model.access.csv
@@ -1,7 +1,7 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"access_purchase_requisition","purchase.requisition","model_purchase_requisition","purchase.group_purchase_user",1,1,1,1
-"access_purchase_requisition_line","purchase.requisition.line","model_purchase_requisition_line","purchase.group_purchase_user",1,1,1,1
+"access_purchase_requisition_line_purchase_user","purchase.requisition.line","model_purchase_requisition_line","purchase.group_purchase_user",1,1,1,1
"access_purchase_requisition_manager","purchase.requisition manager","model_purchase_requisition","purchase.group_purchase_manager",1,0,0,0
"access_purchase_requisition_line_manager","purchase.requisition.line manager","model_purchase_requisition_line","purchase.group_purchase_manager",1,0,0,0
-"access_purchase_requisition","purchase.requisition","model_purchase_requisition","stock.group_stock_manager",1,0,1,0
-"access_purchase_requisition_line","purchase.requisition.line","model_purchase_requisition_line","stock.group_stock_manager",1,0,1,0
+"access_purchase_requisition_stock_manager","purchase.requisition","model_purchase_requisition","stock.group_stock_manager",1,0,1,0
+"access_purchase_requisition_line_stock_manager","purchase.requisition.line","model_purchase_requisition_line","stock.group_stock_manager",1,0,1,0
diff --git a/addons/report_intrastat/report_intrastat_data.xml b/addons/report_intrastat/report_intrastat_data.xml
index f3c465c1549..006151915e2 100644
--- a/addons/report_intrastat/report_intrastat_data.xml
+++ b/addons/report_intrastat/report_intrastat_data.xml
@@ -4,6 +4,9 @@
+
+
+
diff --git a/addons/sale/sale.py b/addons/sale/sale.py
index cd9ae88292e..ba9862f7c18 100644
--- a/addons/sale/sale.py
+++ b/addons/sale/sale.py
@@ -705,7 +705,6 @@ class sale_order(osv.osv):
#'state': 'waiting',
'note': line.notes,
'company_id': order.company_id.id,
- 'returned_price': line.price_unit,
})
if line.product_id:
@@ -739,12 +738,13 @@ class sale_order(osv.osv):
proc_obj.write(cr, uid, [proc_id], {'product_qty': mov.product_qty, 'product_uos_qty': mov.product_uos_qty})
val = {}
- for proc_id in proc_ids:
- wf_service.trg_validate(uid, 'procurement.order', proc_id, 'button_confirm', cr)
if picking_id:
wf_service.trg_validate(uid, 'stock.picking', picking_id, 'button_confirm', cr)
+ for proc_id in proc_ids:
+ wf_service.trg_validate(uid, 'procurement.order', proc_id, 'button_confirm', cr)
+
if order.state == 'shipping_except':
val['state'] = 'progress'
val['shipped'] = False
diff --git a/addons/sale/sale_view.xml b/addons/sale/sale_view.xml
index 3d1a14edd53..15bf57bff9a 100644
--- a/addons/sale/sale_view.xml
+++ b/addons/sale/sale_view.xml
@@ -172,6 +172,7 @@
+
diff --git a/addons/stock/product_view.xml b/addons/stock/product_view.xml
index dca180baeec..24da97c58ea 100644
--- a/addons/stock/product_view.xml
+++ b/addons/stock/product_view.xml
@@ -106,7 +106,7 @@
+ type="action" icon="gtk-execute" groups = "stock.group_stock_manager,stock.group_stock_user"/>
diff --git a/addons/stock/stock.py b/addons/stock/stock.py
index 31a30d233cf..51417c52075 100644
--- a/addons/stock/stock.py
+++ b/addons/stock/stock.py
@@ -864,8 +864,7 @@ class stock_picking(osv.osv):
@return {'contact': address, 'invoice': address} for invoice
"""
partner_obj = self.pool.get('res.partner')
- partner = (picking.purchase_id and picking.purchase_id.partner_id) or (picking.sale_id and picking.sale_id.partner_id) or picking.address_id.partner_id
-
+ partner = picking.address_id.partner_id
return partner_obj.address_get(cr, uid, [partner.id],
['contact', 'invoice'])
@@ -960,6 +959,7 @@ class stock_picking(osv.osv):
invoice_obj = self.pool.get('account.invoice')
invoice_line_obj = self.pool.get('account.invoice.line')
+ address_obj = self.pool.get('res.partner.address')
invoices_group = {}
res = {}
inv_type = type
@@ -983,6 +983,7 @@ class stock_picking(osv.osv):
address_contact_id, address_invoice_id = \
self._get_address_invoice(cr, uid, picking).values()
+ address = address_obj.browse(cr, uid, address_contact_id, context=context)
comment = self._get_comment_invoice(cr, uid, picking)
if group and partner.id in invoices_group:
@@ -1002,7 +1003,7 @@ class stock_picking(osv.osv):
'origin': (picking.name or '') + (picking.origin and (':' + picking.origin) or ''),
'type': inv_type,
'account_id': account_id,
- 'partner_id': partner.id,
+ 'partner_id': address.partner_id.id,
'address_invoice_id': address_invoice_id,
'address_contact_id': address_contact_id,
'comment': comment,
@@ -1159,6 +1160,7 @@ class stock_picking(osv.osv):
complete, too_many, too_few = [], [], []
move_product_qty = {}
prodlot_ids = {}
+ product_avail = {}
for move in pick.move_lines:
if move.state in ('done', 'cancel'):
continue
@@ -1184,6 +1186,12 @@ class stock_picking(osv.osv):
move_currency_id = move.company_id.currency_id.id
context['currency_id'] = move_currency_id
qty = uom_obj._compute_qty(cr, uid, product_uom, product_qty, product.uom_id.id)
+
+ if product.id in product_avail:
+ product_avail[product.id] += qty
+ else:
+ product_avail[product.id] = product.qty_available
+
if qty > 0:
new_price = currency_obj.compute(cr, uid, product_currency,
move_currency_id, product_price)
@@ -1194,9 +1202,8 @@ class stock_picking(osv.osv):
else:
# Get the standard price
amount_unit = product.price_get('standard_price', context)[product.id]
- new_std_price = ((amount_unit * product.qty_available)\
- + (new_price * qty))/(product.qty_available + qty)
-
+ new_std_price = ((amount_unit * product_avail[product.id])\
+ + (new_price * qty))/(product_avail[product.id] + qty)
# Write the field according to price type field
product_obj.write(cr, uid, [product.id], {'standard_price': new_std_price})
@@ -1206,8 +1213,6 @@ class stock_picking(osv.osv):
{'price_unit': product_price,
'price_currency_id': product_currency})
- if not move.returned_price:
- move_obj.write(cr, uid, [move.id], {'returned_price': move.price_unit})
for move in too_few:
product_qty = move_product_qty[move.id]
@@ -1547,7 +1552,6 @@ class stock_move(osv.osv):
# used for colors in tree views:
'scrapped': fields.related('location_dest_id','scrap_location',type='boolean',relation='stock.location',string='Scrapped', readonly=True),
- 'returned_price': fields.float('Returned product price', digits_compute= dp.get_precision('Sale Price')),
}
_constraints = [
(_check_tracking,
@@ -1784,7 +1788,7 @@ class stock_move(osv.osv):
picking_obj = self.pool.get('stock.picking')
pick_id= picking_obj.create(cr, uid, {
'name': pick_name,
- 'origin': str(picking.origin or ''),
+ 'origin': tools.ustr(picking.origin or ''),
'type': ptype,
'note': picking.note,
'move_type': picking.move_type,
@@ -1796,6 +1800,51 @@ class stock_move(osv.osv):
'date': picking.date,
})
return pick_id
+ def create_chained_picking(self, cr, uid, moves, context=None):
+ res_obj = self.pool.get('res.company')
+ location_obj = self.pool.get('stock.location')
+ move_obj = self.pool.get('stock.move')
+ wf_service = netsvc.LocalService("workflow")
+ new_moves = []
+ if context is None:
+ context = {}
+ seq_obj = self.pool.get('ir.sequence')
+ for picking, todo in self._chain_compute(cr, uid, moves, context=context).items():
+ ptype = todo[0][1][5] and todo[0][1][5] or location_obj.picking_type_get(cr, uid, todo[0][0].location_dest_id, todo[0][1][0])
+ if picking:
+ # name of new picking according to its type
+ new_pick_name = seq_obj.get(cr, uid, 'stock.picking.' + ptype)
+ pickid = self._create_chained_picking(cr, uid, new_pick_name, picking, ptype, todo, context=context)
+ # Need to check name of old picking because it always considers picking as "OUT" when created from Sale Order
+ old_ptype = location_obj.picking_type_get(cr, uid, picking.move_lines[0].location_id, picking.move_lines[0].location_dest_id)
+ if old_ptype != picking.type:
+ old_pick_name = seq_obj.get(cr, uid, 'stock.picking.' + old_ptype)
+ self.pool.get('stock.picking').write(cr, uid, picking.id, {'name': old_pick_name}, context=context)
+ else:
+ pickid = False
+ for move, (loc, dummy, delay, dummy, company_id, ptype) in todo:
+ new_id = move_obj.copy(cr, uid, move.id, {
+ 'location_id': move.location_dest_id.id,
+ 'location_dest_id': loc.id,
+ 'date_moved': time.strftime('%Y-%m-%d'),
+ 'picking_id': pickid,
+ 'state': 'waiting',
+ 'company_id': company_id or res_obj._company_default_get(cr, uid, 'stock.company', context=context) ,
+ 'move_history_ids': [],
+ 'date': (datetime.strptime(move.date, '%Y-%m-%d %H:%M:%S') + relativedelta(days=delay or 0)).strftime('%Y-%m-%d'),
+ 'move_history_ids2': []}
+ )
+ move_obj.write(cr, uid, [move.id], {
+ 'move_dest_id': new_id,
+ 'move_history_ids': [(4, new_id)]
+ })
+ new_moves.append(self.browse(cr, uid, [new_id])[0])
+ if pickid:
+ wf_service.trg_validate(uid, 'stock.picking', pickid, 'button_confirm', cr)
+ if new_moves:
+ new_moves += self.create_chained_picking(cr, uid, new_moves, context)
+ return new_moves
+
def action_confirm(self, cr, uid, ids, context=None):
""" Confirms stock move.
@return: List of ids.
@@ -1807,46 +1856,7 @@ class stock_move(osv.osv):
move_obj = self.pool.get('stock.move')
wf_service = netsvc.LocalService("workflow")
- def create_chained_picking(self, cr, uid, moves, context=None):
- new_moves = []
- if context is None:
- context = {}
- seq_obj = self.pool.get('ir.sequence')
- for picking, todo in self._chain_compute(cr, uid, moves, context=context).items():
- ptype = todo[0][1][5] and todo[0][1][5] or location_obj.picking_type_get(cr, uid, todo[0][0].location_dest_id, todo[0][1][0])
- if picking:
- # name of new picking according to its type
- new_pick_name = seq_obj.get(cr, uid, 'stock.picking.' + ptype)
- pickid = self._create_chained_picking(cr, uid, new_pick_name, picking, ptype, todo, context=context)
- # Need to check name of old picking because it always considers picking as "OUT" when created from Sale Order
- old_ptype = location_obj.picking_type_get(cr, uid, picking.move_lines[0].location_id, picking.move_lines[0].location_dest_id)
- if old_ptype != picking.type:
- old_pick_name = seq_obj.get(cr, uid, 'stock.picking.' + old_ptype)
- self.pool.get('stock.picking').write(cr, uid, picking.id, {'name': old_pick_name}, context=context)
- else:
- pickid = False
- for move, (loc, dummy, delay, dummy, company_id, ptype) in todo:
- new_id = move_obj.copy(cr, uid, move.id, {
- 'location_id': move.location_dest_id.id,
- 'location_dest_id': loc.id,
- 'date_moved': time.strftime('%Y-%m-%d'),
- 'picking_id': pickid,
- 'state': 'waiting',
- 'company_id': company_id or res_obj._company_default_get(cr, uid, 'stock.company', context=context) ,
- 'move_history_ids': [],
- 'date': (datetime.strptime(move.date, '%Y-%m-%d %H:%M:%S') + relativedelta(days=delay or 0)).strftime('%Y-%m-%d'),
- 'move_history_ids2': []}
- )
- move_obj.write(cr, uid, [move.id], {
- 'move_dest_id': new_id,
- 'move_history_ids': [(4, new_id)]
- })
- new_moves.append(self.browse(cr, uid, [new_id])[0])
- if pickid:
- wf_service.trg_validate(uid, 'stock.picking', pickid, 'button_confirm', cr)
- if new_moves:
- create_chained_picking(self, cr, uid, new_moves, context)
- create_chained_picking(self, cr, uid, moves, context)
+ self.create_chained_picking(cr, uid, moves, context)
return []
def action_assign(self, cr, uid, ids, *args):
@@ -2114,6 +2124,8 @@ class stock_move(osv.osv):
prodlot_id = partial_datas and partial_datas.get('move%s_prodlot_id' % (move.id), False)
if prodlot_id:
self.write(cr, uid, [move.id], {'prodlot_id': prodlot_id}, context=context)
+ if move.state not in ('confirmed','done'):
+ self.action_confirm(cr, uid, move_ids, context=context)
self.write(cr, uid, move_ids, {'state': 'done', 'date_planned': time.strftime('%Y-%m-%d %H:%M:%S')}, context=context)
for id in move_ids:
@@ -2218,6 +2230,8 @@ class stock_move(osv.osv):
'tracking_id': move.tracking_id.id,
'prodlot_id': move.prodlot_id.id,
}
+ if move.location_id.usage <> 'internal':
+ default_val.update({'location_id': move.location_dest_id.id})
new_move = self.copy(cr, uid, move.id, default_val)
res += [new_move]
@@ -2568,22 +2582,33 @@ class stock_inventory(osv.osv):
self.write(cr, uid, [inv.id], {'state': 'confirm', 'move_ids': [(6, 0, move_ids)]})
return True
- def action_cancel(self, cr, uid, ids, context=None):
+ def action_cancel_draft(self, cr, uid, ids, context=None):
""" Cancels the stock move and change inventory state to draft.
@return: True
"""
for inv in self.browse(cr, uid, ids, context=context):
- self.pool.get('stock.move').action_cancel(cr, uid, [x.id for x in inv.move_ids], context)
- self.write(cr, uid, [inv.id], {'state': 'draft'})
+ self.pool.get('stock.move').action_cancel(cr, uid, [x.id for x in inv.move_ids], context=context)
+ self.write(cr, uid, [inv.id], {'state':'draft'}, context=context)
return True
def action_cancel_inventary(self, cr, uid, ids, context=None):
""" Cancels both stock move and inventory
@return: True
"""
+ move_obj = self.pool.get('stock.move')
+ account_move_obj = self.pool.get('account.move')
for inv in self.browse(cr, uid, ids, context=context):
- self.pool.get('stock.move').action_cancel(cr, uid, [x.id for x in inv.move_ids], context)
- self.write(cr, uid, [inv.id], {'state':'cancel'})
+ move_obj.action_cancel(cr, uid, [x.id for x in inv.move_ids], context=context)
+ for move in inv.move_ids:
+ account_move_ids = account_move_obj.search(cr, uid, [('name', '=', move.name)])
+ if account_move_ids:
+ account_move_data_l = account_move_obj.read(cr, uid, account_move_ids, ['state'], context=context)
+ for account_move in account_move_data_l:
+ if account_move['state'] == 'posted':
+ raise osv.except_osv(_('UserError'),
+ _('You can not cancel inventory which has any account move with posted state.'))
+ account_move_obj.unlink(cr, uid, [account_move['id']], context=context)
+ self.write(cr, uid, [inv.id], {'state': 'cancel'}, context=context)
return True
stock_inventory()
diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml
index 80e63ebef23..13684b3999a 100644
--- a/addons/stock/stock_view.xml
+++ b/addons/stock/stock_view.xml
@@ -170,11 +170,11 @@
-
-
+
+
-
+
@@ -773,7 +773,7 @@
-
+
@@ -967,7 +967,7 @@
-
+
@@ -1189,7 +1189,7 @@
-
+
diff --git a/addons/stock/wizard/stock_change_product_qty.py b/addons/stock/wizard/stock_change_product_qty.py
index 897d5cd0e98..c22ade231be 100644
--- a/addons/stock/wizard/stock_change_product_qty.py
+++ b/addons/stock/wizard/stock_change_product_qty.py
@@ -32,6 +32,19 @@ class stock_change_product_qty(osv.osv_memory):
'location_id': fields.many2one('stock.location', 'Location', required=True, domain="[('usage', '=', 'internal')]"),
}
+ def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
+ result = super(stock_change_product_qty, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu)
+ product_id = context and context.get('active_id', False) or False
+
+ if (context.get('active_model') == 'product.product') and product_id:
+ prod_obj = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
+ fields = result.get('fields', {})
+ if fields and (prod_obj.track_production == True) and (fields.get('prodlot_id')):
+ result['fields']['prodlot_id']['required'] = True
+ else:
+ result['fields']['prodlot_id']['required'] = False
+ return result
+
def default_get(self, cr, uid, fields, context):
""" To get default values for the object.
@param self: The object pointer.
diff --git a/addons/stock/wizard/stock_invoice_onshipping.py b/addons/stock/wizard/stock_invoice_onshipping.py
index 091049b5689..c7eab1eef4d 100644
--- a/addons/stock/wizard/stock_invoice_onshipping.py
+++ b/addons/stock/wizard/stock_invoice_onshipping.py
@@ -85,34 +85,18 @@ class stock_invoice_onshipping(osv.osv_memory):
raise osv.except_osv(_('Warning !'), _('None of these picking lists require invoicing.'))
return res
-
-
- def create_invoice(self, cr, uid, ids, context=None):
+ def open_invoice(self, cr, uid, ids, context=None):
if context is None:
context = {}
- picking_pool = self.pool.get('stock.picking')
- data_pool = self.pool.get('ir.model.data')
- onshipdata_obj = self.read(cr, uid, ids[0], ['journal_id', 'group', 'invoice_date'])
- if context.get('new_picking', False):
- onshipdata_obj['id'] = onshipdata_obj.new_picking
- onshipdata_obj[ids] = onshipdata_obj.new_picking
-
- context['date_inv'] = onshipdata_obj['invoice_date']
invoice_ids = []
- active_ids = context.get('active_ids', [])
- active_picking = picking_pool.browse(cr, uid, context.get('active_id',False), context=context)
- inv_type = picking_pool._get_invoice_type(active_picking)
-
- res = picking_pool.action_invoice_create(cr, uid, active_ids,
- journal_id = onshipdata_obj['journal_id'],
- group = onshipdata_obj['group'],
- type = None,
- context=context)
+ data_pool = self.pool.get('ir.model.data')
+ res = self.create_invoice(cr, uid, ids, context=context)
invoice_ids += res.values()
- if not invoice_ids:
- raise osv.except_osv(_('Error'), _('No Invoices were created'))
+ inv_type = context.get('inv_type', False)
action_model = False
action = {}
+ if not invoice_ids:
+ raise osv.except_osv(_('Error'), _('No Invoices were created'))
if inv_type == "out_invoice":
action_model,action_id = data_pool.get_object_reference(cr, uid, 'account', "action_invoice_tree1")
elif inv_type == "in_invoice":
@@ -127,6 +111,26 @@ class stock_invoice_onshipping(osv.osv_memory):
action['domain'] = "[('id','in', ["+','.join(map(str,invoice_ids))+"])]"
return action
+ def create_invoice(self, cr, uid, ids, context=None):
+ if context is None:
+ context = {}
+ picking_pool = self.pool.get('stock.picking')
+ onshipdata_obj = self.read(cr, uid, ids, ['journal_id', 'group', 'invoice_date'])
+ if context.get('new_picking', False):
+ onshipdata_obj['id'] = onshipdata_obj.new_picking
+ onshipdata_obj[ids] = onshipdata_obj.new_picking
+ context['date_inv'] = onshipdata_obj[0]['invoice_date']
+ active_ids = context.get('active_ids', [])
+ active_picking = picking_pool.browse(cr, uid, context.get('active_id',False), context=context)
+ inv_type = picking_pool._get_invoice_type(active_picking)
+ context['inv_type'] = inv_type
+ res = picking_pool.action_invoice_create(cr, uid, active_ids,
+ journal_id = onshipdata_obj[0]['journal_id'],
+ group = onshipdata_obj[0]['group'],
+ type = None,
+ context=context)
+ return res
+
stock_invoice_onshipping()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/stock/wizard/stock_invoice_onshipping_view.xml b/addons/stock/wizard/stock_invoice_onshipping_view.xml
index 6a4cfec5fca..06d93f49ea1 100644
--- a/addons/stock/wizard/stock_invoice_onshipping_view.xml
+++ b/addons/stock/wizard/stock_invoice_onshipping_view.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/addons/stock/wizard/stock_partial_picking.py b/addons/stock/wizard/stock_partial_picking.py
index d9822fff6b1..5d15b3715bd 100644
--- a/addons/stock/wizard/stock_partial_picking.py
+++ b/addons/stock/wizard/stock_partial_picking.py
@@ -33,51 +33,71 @@ class stock_partial_picking(osv.osv_memory):
'product_moves_in' : fields.one2many('stock.move.memory.in', 'wizard_id', 'Moves'),
}
- def __is_in(self,cr, uid, pick_ids):
+ def get_picking_type(self, cr, uid, picking, context=None):
+ picking_type = picking.type
+ for move in picking.move_lines:
+ if picking.type == 'in' and move.product_id.cost_method == 'average':
+ picking_type = 'in'
+ break
+ else:
+ picking_type = 'out'
+ return picking_type
+
+ def default_get(self, cr, uid, fields, context=None):
+ """ To get default values for the object.
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param fields: List of fields for which we want default values
+ @param context: A standard dictionary
+ @return: A dictionary which of fields with values.
"""
- @return: True if one of the moves has as picking type 'in'
- """
- if not pick_ids:
- return False
+ if context is None:
+ context = {}
+
+ pick_obj = self.pool.get('stock.picking')
+ res = super(stock_partial_picking, self).default_get(cr, uid, fields, context=context)
+ picking_ids = context.get('active_ids', [])
+ if not picking_ids:
+ return res
+
+ result = []
+ for pick in pick_obj.browse(cr, uid, picking_ids, context=context):
+ pick_type = self.get_picking_type(cr, uid, pick, context=context)
+ for m in pick.move_lines:
+ if m.state in ('done', 'cancel'):
+ continue
+ result.append(self.__create_partial_picking_memory(m, pick_type))
+
+ if 'product_moves_in' in fields:
+ res.update({'product_moves_in': result})
+ if 'product_moves_out' in fields:
+ res.update({'product_moves_out': result})
+ if 'date' in fields:
+ res.update({'date': time.strftime('%Y-%m-%d %H:%M:%S')})
+ return res
+
+ def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
+ result = super(stock_partial_picking, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu)
pick_obj = self.pool.get('stock.picking')
- pick_ids = pick_obj.search(cr, uid, [('id','in',pick_ids)])
-
-
- for pick in pick_obj.browse(cr, uid, pick_ids):
- for move in pick.move_lines:
- if pick.type == 'in' and move.product_id.cost_method == 'average':
- return True
- return False
-
- def __get_picking_type(self, cr, uid, pick_ids):
- if self.__is_in(cr, uid, pick_ids):
- return "product_moves_in"
- else:
- return "product_moves_out"
-
- def view_init(self, cr, uid, fields_list, context=None):
- res = super(stock_partial_picking, self).view_init(cr, uid, fields_list, context=context)
- return res
-
- def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False,submenu=False):
- result = super(stock_partial_picking, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar,submenu)
-
-
picking_ids = context.get('active_ids', False)
- picking_type = self.__get_picking_type(cr, uid, picking_ids)
+
+ for pick in pick_obj.browse(cr, uid, picking_ids, context=context):
+ picking_type = self.get_picking_type(cr, uid, pick, context=context)
_moves_arch_lst = """