diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml index a56d850a8e3..0a19b304c17 100644 --- a/addons/account/account_view.xml +++ b/addons/account/account_view.xml @@ -558,6 +558,7 @@ + @@ -2572,7 +2573,7 @@ action = self.pool.get('res.config').next(cr, uid, [], context) - +
@@ -2582,7 +2583,7 @@ action = self.pool.get('res.config').next(cr, uid, [], context) - + 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.py b/addons/crm/crm_meeting.py index cbc12cec248..2c4edc02df7 100644 --- a/addons/crm/crm_meeting.py +++ b/addons/crm/crm_meeting.py @@ -146,7 +146,7 @@ class res_users(osv.osv): 'user_id': user_id}, context=context) except: # Tolerate a missing shortcut. See product/product.py for similar code. - logging.getLogger('orm').warning('Skipped Products shortcut for user "%s"', data.get('name',' - - 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/hr/hr.py b/addons/hr/hr.py index e2b9a7089f3..9f75082ab8c 100644 --- a/addons/hr/hr.py +++ b/addons/hr/hr.py @@ -146,7 +146,7 @@ class hr_employee(osv.osv): 'marital': fields.many2one('hr.employee.marital.status', 'Marital Status'), 'department_id':fields.many2one('hr.department', 'Department'), 'address_id': fields.many2one('res.partner.address', 'Working Address'), - 'address_home_id': fields.many2one('res.partner.address', 'Home Address'), + 'address_home_id': fields.many2one('res.partner.address', 'Home Address', domain="[('partner_id', '!=', False)]"), 'partner_id': fields.related('address_home_id', 'partner_id', type='many2one', relation='res.partner', readonly=True, help="Partner that is related to the current employee. Accounting transaction will be written on this partner belongs to employee."), 'bank_account_id':fields.many2one('res.partner.bank', 'Bank Account', domain="[('partner_id','=',partner_id)]", help="Employee bank salary account"), 'work_phone': fields.char('Work Phone', size=32, readonly=False), diff --git a/addons/hr_attendance/report/attendance_by_month.py b/addons/hr_attendance/report/attendance_by_month.py index c8d0378b971..03246b4bab6 100644 --- a/addons/hr_attendance/report/attendance_by_month.py +++ b/addons/hr_attendance/report/attendance_by_month.py @@ -29,6 +29,7 @@ from report.interface import report_rml from report.interface import toxml from report import report_sxw +from tools import ustr one_day = relativedelta(days=1) month2name = [0, 'January', 'February', 'March', 'April', 'May', 'Jun', 'July', 'August', 'September', 'October', 'November', 'December'] @@ -60,7 +61,7 @@ class report_custom(report_rml): %s %%s - ''' % (toxml(emp['name'])) + ''' % (ustr(emp['name'])) today, tomor = month, month + one_day while today.month == month.month: #### Work hour calculation diff --git a/addons/hr_attendance/security/ir_rule.xml b/addons/hr_attendance/security/ir_rule.xml index 5f93aa2a4fd..92534da7dc0 100644 --- a/addons/hr_attendance/security/ir_rule.xml +++ b/addons/hr_attendance/security/ir_rule.xml @@ -14,6 +14,12 @@ [(1,'=',1)] + + Employee Attendance + + [('employee_id.user_id','=',user.id)] + + diff --git a/addons/hr_expense/hr_expense.py b/addons/hr_expense/hr_expense.py index 9cb53f81dce..afc9ee57a11 100644 --- a/addons/hr_expense/hr_expense.py +++ b/addons/hr_expense/hr_expense.py @@ -251,13 +251,17 @@ class hr_expense_line(osv.osv): product = self.pool.get('product.product').browse(cr, uid, product_id, context=context) res['name'] = product.name # Compute based on pricetype of employee company - ctx['currency_id'] = self.pool.get('hr.employee').browse(cr, uid, employee_id, context=context).user_id.company_id.currency_id.id - amount_unit = product.price_get('standard_price', ctx)[product.id] - res['unit_amount'] = amount_unit + employee = self.pool.get('hr.employee').browse(cr, uid, employee_id, context=context) + if employee.user_id: + ctx['currency_id'] = self.pool.get('hr.employee').browse(cr, uid, employee_id, context=context).user_id.company_id.currency_id.id + amount_unit = product.price_get('standard_price', ctx)[product.id] + res['unit_amount'] = amount_unit + else: + res['unit_amount'] = product.standard_price if not uom_id: res['uom_id'] = product.uom_id.id return {'value': res} hr_expense_line() -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file diff --git a/addons/hr_expense/security/ir_rule.xml b/addons/hr_expense/security/ir_rule.xml index 4807cf38465..292db38bf5e 100644 --- a/addons/hr_expense/security/ir_rule.xml +++ b/addons/hr_expense/security/ir_rule.xml @@ -14,6 +14,12 @@ [(1,'=',1)] + + Employee Expense + + [('employee_id.user_id','=',user.id)] + + diff --git a/addons/hr_holidays/report/holidays_summary_report.py b/addons/hr_holidays/report/holidays_summary_report.py index 92dedd1a14d..a7d9e16accc 100644 --- a/addons/hr_holidays/report/holidays_summary_report.py +++ b/addons/hr_holidays/report/holidays_summary_report.py @@ -29,6 +29,7 @@ from report.interface import toxml import pooler import time from report import report_sxw +from tools import ustr def lengthmonth(year, month): if month == 2 and ((year % 4 == 0) and ((year % 100 != 0) or (year % 400 == 0))): @@ -244,7 +245,7 @@ class report_custom(report_rml): %s %s - ''' % (header_xml,months_xml,date_xml, emp_xml) + ''' % (header_xml,months_xml,date_xml, ustr(emp_xml)) return xml diff --git a/addons/hr_holidays/security/ir_rule.xml b/addons/hr_holidays/security/ir_rule.xml index cbb425fa103..9a56336dcdc 100644 --- a/addons/hr_holidays/security/ir_rule.xml +++ b/addons/hr_holidays/security/ir_rule.xml @@ -14,6 +14,12 @@ [(1,'=',1)] + + Employee Holidays + + [('employee_id.user_id','=',user.id)] + + diff --git a/addons/hr_timesheet/report/user_timesheet.py b/addons/hr_timesheet/report/user_timesheet.py index 4d1d5f428cf..fd2206cbc80 100644 --- a/addons/hr_timesheet/report/user_timesheet.py +++ b/addons/hr_timesheet/report/user_timesheet.py @@ -27,6 +27,7 @@ from tools.translate import _ import time import pooler from report import report_sxw +from tools import ustr def lengthmonth(year, month): if month == 2 and ((year % 4 == 0) and ((year % 100 != 0) or (year % 400 == 0))): @@ -49,7 +50,7 @@ class report_custom(report_rml): emp_obj = pooler.get_pool(cr.dbname).get('hr.employee') user_id = emp_obj.browse(cr, uid, emp_id).user_id.id empl_name = emp_obj.browse(cr, uid, emp_id).name - + # Computing the dates (start of month: som, and end of month: eom) som = datetime.date(data['form']['year'], data['form']['month'], 1) eom = som + datetime.timedelta(lengthmonth(som.year, som.month)) @@ -109,7 +110,7 @@ class report_custom(report_rml): %s %s - ''' % (header_xml,toxml(empl_name), '\n'.join(date_xml) + '\n'.join(account_xml)) + ''' % (header_xml, ustr(empl_name), '\n'.join(date_xml) + '\n'.join(account_xml)) return xml report_custom('report.hr.analytical.timesheet', 'hr.employee', '', 'addons/hr_timesheet/report/user_timesheet.xsl') diff --git a/addons/hr_timesheet/report/users_timesheet.py b/addons/hr_timesheet/report/users_timesheet.py index e6b366d627a..fac92d6a322 100644 --- a/addons/hr_timesheet/report/users_timesheet.py +++ b/addons/hr_timesheet/report/users_timesheet.py @@ -26,6 +26,7 @@ import time import pooler from tools.translate import _ from report import report_sxw +from tools import ustr def lengthmonth(year, month): @@ -111,7 +112,7 @@ class report_custom(report_rml): %s %s - ''' % (header_xml,date_xml, emp_xml) + ''' % (header_xml,date_xml, ustr(emp_xml)) return xml report_custom('report.hr.analytical.timesheet_users', 'hr.employee', '', 'addons/hr_timesheet/report/users_timesheet.xsl') diff --git a/addons/mail_gateway/mail_gateway.py b/addons/mail_gateway/mail_gateway.py index ed5489fda79..15c5bba7c64 100644 --- a/addons/mail_gateway/mail_gateway.py +++ b/addons/mail_gateway/mail_gateway.py @@ -25,6 +25,7 @@ import tools import binascii import email from email.header import decode_header +from email.utils import parsedate import base64 import re from tools.translate import _ @@ -111,6 +112,11 @@ class mailgate_thread(osv.osv): if attach is None: attach = [] + if email_date: + edate = parsedate(email_date) + if edate is not None: + email_date = time.strftime('%Y-%m-%d %H:%M:%S', edate) + # The mailgate sends the ids of the cases and not the object list if all(isinstance(case_id, (int, long)) for case_id in cases): 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 @@ -