diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py index 43aaa2f58c1..a380a69dc03 100644 --- a/addons/account/__openerp__.py +++ b/addons/account/__openerp__.py @@ -99,7 +99,6 @@ for a particular financial year and for preparation of vouchers there is a modul 'project/wizard/project_account_analytic_line_view.xml', 'account_end_fy.xml', 'account_invoice_view.xml', - 'partner_view.xml', 'data/account_data.xml', 'data/data_account_type.xml', 'data/configurable_account_chart.xml', @@ -112,6 +111,7 @@ for a particular financial year and for preparation of vouchers there is a modul 'project/wizard/account_analytic_journal_report_view.xml', 'project/wizard/account_analytic_cost_ledger_for_journal_report_view.xml', 'project/wizard/account_analytic_chart_view.xml', + 'partner_view.xml', 'product_view.xml', 'account_assert_test.xml', 'process/statement_process.xml', diff --git a/addons/account/account.py b/addons/account/account.py index 3959799f1bb..e92bd3a7879 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -1670,7 +1670,7 @@ class account_move_reconcile(osv.osv): elif reconcile.line_partial_ids: first_partner = reconcile.line_partial_ids[0].partner_id.id move_lines = reconcile.line_partial_ids - if any([line.partner_id.id != first_partner for line in move_lines]): + if any([(line.account_id.type in ('receivable', 'payable') and line.partner_id.id != first_partner) for line in move_lines]): return False return True diff --git a/addons/account/account_financial_report_data.xml b/addons/account/account_financial_report_data.xml index 6410a5e887c..e8ff33151c3 100644 --- a/addons/account/account_financial_report_data.xml +++ b/addons/account/account_financial_report_data.xml @@ -6,16 +6,19 @@ --> Profit and Loss + sum Income + detail_with_hierarchy account_type Expense + detail_with_hierarchy account_type diff --git a/addons/account/account_installer.xml b/addons/account/account_installer.xml index 58e824a6250..b03babc63ac 100644 --- a/addons/account/account_installer.xml +++ b/addons/account/account_installer.xml @@ -20,10 +20,11 @@

+ - + diff --git a/addons/point_of_sale/wizard/pos_session_opening.py b/addons/point_of_sale/wizard/pos_session_opening.py index 039dd90ae6b..39e7c564831 100644 --- a/addons/point_of_sale/wizard/pos_session_opening.py +++ b/addons/point_of_sale/wizard/pos_session_opening.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python from openerp.osv import osv, fields from openerp.tools.translate import _ diff --git a/addons/portal/__init__.py b/addons/portal/__init__.py index 0045a557a49..e7026986ea4 100644 --- a/addons/portal/__init__.py +++ b/addons/portal/__init__.py @@ -21,6 +21,7 @@ import portal import mail_mail +import mail_message import wizard import acquirer diff --git a/addons/portal/mail_mail.py b/addons/portal/mail_mail.py index bc982671bfe..967822c7d60 100644 --- a/addons/portal/mail_mail.py +++ b/addons/portal/mail_mail.py @@ -21,7 +21,6 @@ from openerp import SUPERUSER_ID from openerp.osv import osv -from openerp.osv.orm import except_orm from openerp.tools.translate import _ @@ -35,21 +34,14 @@ class mail_mail(osv.Model): :param partner: browse_record of the specific recipient partner :return: the resulting body_html """ + if context is None: + context = {} partner_obj = self.pool.get('res.partner') - if partner: - contex_signup = dict(context or {}, signup_valid=True) - partner = partner_obj.browse(cr, SUPERUSER_ID, partner.id, context=contex_signup) - body_footer = _("""Access your messages and documents through our Customer Portal""") % partner.signup_url - # partner is an user: add a link to the document if read access - if partner.user_ids and mail.model and mail.res_id \ - and self.check_access_rights(cr, partner.user_ids[0].id, 'read', raise_exception=False): - related_user = partner.user_ids[0] - try: - self.pool[mail.model].check_access_rule(cr, related_user.id, [mail.res_id], 'read', context=context) - url = partner_obj._get_signup_url_for_action(cr, related_user.id, [partner.id], action='', res_id=mail.res_id, model=mail.model, context=context)[partner.id] - text = _("""Access this document directly in OpenERP""") % url - except except_orm, e: - pass - return body_footer + if partner and not partner.user_ids: + contex_signup = dict(context, signup_valid=True) + signup_url = partner_obj._get_signup_url_for_action(cr, SUPERUSER_ID, [partner.id], + action='login', model=mail.model, res_id=mail.res_id, + context=contex_signup)[partner.id] + return _("""Access your messages and documents through our Customer Portal""") % signup_url else: return super(mail_mail, self).send_get_mail_body_footer(cr, uid, mail, partner=partner, context=context) diff --git a/addons/portal/mail_message.py b/addons/portal/mail_message.py new file mode 100644 index 00000000000..d6a38f27378 --- /dev/null +++ b/addons/portal/mail_message.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2011 OpenERP S.A (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.osv import osv, orm +from openerp.tools.translate import _ + + +class mail_message(osv.Model): + """ Update of mail_message class, to restrict mail access. """ + _inherit = 'mail.message' + + def _search(self, cr, uid, args, offset=0, limit=None, order=None, + context=None, count=False, access_rights_uid=None): + """ Override that adds specific access rights of mail.message, to remove + all internal notes if uid is a non-employee + """ + group_ids = self.pool.get('res.users').browse(cr, uid, uid, context=context).groups_id + group_user_id = self.pool.get("ir.model.data").get_object_reference(cr, uid, 'base', 'group_user')[1] + if group_user_id not in [group.id for group in group_ids]: + args = ['&', '|', ('type', '!=', 'comment'), ('subtype_id', '!=', False)] + list(args) + + return super(mail_message, self)._search(cr, uid, args, offset=offset, limit=limit, order=order, + context=context, count=False, access_rights_uid=access_rights_uid) + + def check_access_rule(self, cr, uid, ids, operation, context=None): + """ Add Access rules of mail.message for non-employee user: + - read: + - raise if the type is comment and subtype NULL (internal note) + """ + group_ids = self.pool.get('res.users').browse(cr, uid, uid, context=context).groups_id + group_user_id = self.pool.get("ir.model.data").get_object_reference(cr, uid, 'base', 'group_user')[1] + if group_user_id not in [group.id for group in group_ids]: + cr.execute('SELECT DISTINCT id FROM "%s" WHERE type = %%s AND subtype_id IS NULL AND id = ANY (%%s)' % (self._table), ('comment', ids,)) + if cr.fetchall(): + raise orm.except_orm(_('Access Denied'), + _('The requested operation cannot be completed due to security restrictions. Please contact your system administrator.\n\n(Document type: %s, Operation: %s)') % \ + (self._description, operation)) + + return super(mail_message, self).check_access_rule(cr, uid, ids=ids, operation=operation, context=context) diff --git a/addons/portal/portal_demo.xml b/addons/portal/portal_demo.xml index c05189fd2ab..3660754b4ad 100644 --- a/addons/portal/portal_demo.xml +++ b/addons/portal/portal_demo.xml @@ -40,7 +40,7 @@ Mr Demo Portal mail.group - As your first portal member, I am very pleased to be able to be able to communicate directly with you. Be sure I'll read all news carefully!

]]>
+ As your first portal member, I am very pleased to be able to communicate directly with you. Be sure I'll read all news carefully!

]]>
comment diff --git a/addons/portal/tests/test_portal.py b/addons/portal/tests/test_portal.py index 07becf5cdd9..e96cbc263f6 100644 --- a/addons/portal/tests/test_portal.py +++ b/addons/portal/tests/test_portal.py @@ -40,7 +40,9 @@ class test_portal(TestMailBase): self.partner_chell_id = self.user_chell.partner_id.id # Create a PigsPortal group - self.group_port_id = self.mail_group.create(cr, uid, {'name': 'PigsPortal', 'public': 'groups', 'group_public_id': self.group_portal_id}) + self.group_port_id = self.mail_group.create(cr, uid, + {'name': 'PigsPortal', 'public': 'groups', 'group_public_id': self.group_portal_id}, + {'mail_create_nolog': True}) # Set an email address for the user running the tests, used as Sender for outgoing mails self.res_users.write(cr, uid, uid, {'email': 'test@localhost'}) @@ -130,3 +132,28 @@ class test_portal(TestMailBase): 'invite: body of invitation email is incorrect') self.assertTrue(partner_carine.signup_url in sent_email.get('body'), 'invite: body of invitation email does not contain signup url') + + def test_20_message_read(self): + cr, uid, group_port_id = self.cr, self.uid, self.group_port_id + + # Data: custom subtypes + mt_group_public_id = self.mail_message_subtype.create(cr, uid, {'name': 'group_public', 'description': 'Group changed'}) + self.ir_model_data.create(cr, uid, {'name': 'mt_group_public', 'model': 'mail.message.subtype', 'module': 'mail', 'res_id': mt_group_public_id}) + # Data: post messages with various subtypes + msg1_id = self.mail_group.message_post(cr, uid, group_port_id, body='Body1', type='comment', subtype='mail.mt_comment') + msg2_id = self.mail_group.message_post(cr, uid, group_port_id, body='Body2', type='comment', subtype='mail.mt_group_public') + msg3_id = self.mail_group.message_post(cr, uid, group_port_id, body='Body3', type='comment', subtype='mail.mt_comment') + msg4_id = self.mail_group.message_post(cr, uid, group_port_id, body='Body4', type='comment') + msg5_id = self.mail_group.message_post(cr, uid, group_port_id, body='Body5', type='notification') + + # Do: Chell search messages: should not see internal notes (comment without subtype) + msg_ids = self.mail_message.search(cr, self.user_chell_id, [('model', '=', 'mail.group'), ('res_id', '=', group_port_id)]) + self.assertEqual(set(msg_ids), set([msg1_id, msg2_id, msg3_id, msg5_id]), + 'mail_message: portal user has access to messages he should not read') + + # Do: Chell read messages she can read + self.mail_message.read(cr, self.user_chell_id, msg_ids, ['body', 'type', 'subtype_id']) + + # Do: Chell read a message she should not be able to read + with self.assertRaises(except_orm): + self.mail_message.read(cr, self.user_chell_id, [msg4_id], ['body', 'type', 'subtype_id']) diff --git a/addons/portal_event/portal_event_view.xml b/addons/portal_event/portal_event_view.xml old mode 100755 new mode 100644 diff --git a/addons/portal_hr_employees/hr_employee_view.xml b/addons/portal_hr_employees/hr_employee_view.xml index a3182cd5b1c..ace0daaff87 100644 --- a/addons/portal_hr_employees/hr_employee_view.xml +++ b/addons/portal_hr_employees/hr_employee_view.xml @@ -35,11 +35,35 @@ HR - Employess Kanban hr.employee - - - - + + + + +
+
+ +
+
+

+ +

+
    +
  • +
  • +
  • Tel:
  • +
  • Mobile:
  • +
  • +
  • +
+
+
+ +
+
+
diff --git a/addons/portal_project/security/portal_security.xml b/addons/portal_project/security/portal_security.xml index 8d58ed70aeb..67e57766ebd 100644 --- a/addons/portal_project/security/portal_security.xml +++ b/addons/portal_project/security/portal_security.xml @@ -33,27 +33,26 @@
- Project/Task: employees: public, portal, employee or following or assigned + Project/Task: employees: public, portal, employee or (followers and following) ['|', - ('user_id', '=', user.id), - '|', - ('project_id.privacy_visibility', 'in', ['public', 'portal', 'employees']), - '&', - ('project_id.privacy_visibility', '=', 'followers'), - ('message_follower_ids', 'in', [user.partner_id.id]), + ('project_id.privacy_visibility', 'in', ['public', 'portal', 'employees']), + '&', + ('project_id.privacy_visibility', '=', 'followers'), + ('message_follower_ids', 'in', [user.partner_id.id]), ] - Project/Task: portal users: public or portal and following + Project/Task: portal users: public or (portal and colleagues following) or (followers and following) - ['|', - ('project_id.privacy_visibility', '=', 'public'), + ['|', '|', + ('project_id.privacy_visibility', 'in', ['public']), '&', - ('project_id.privacy_visibility', 'in', ['portal', 'followers']), - '|', - ('message_follower_ids','in', [user.partner_id.id]), - ('user_id', '=', user.id), + ('project_id.privacy_visibility', '=', 'portal'), + ('message_follower_ids', 'child_of', [user.partner_id.commercial_partner_id.id]), + '&', + ('project_id.privacy_visibility', '=', 'followers'), + ('message_follower_ids', 'in', [user.partner_id.id]), ] diff --git a/addons/portal_project_issue/security/portal_security.xml b/addons/portal_project_issue/security/portal_security.xml index f6cd8d89be7..598c1620a82 100644 --- a/addons/portal_project_issue/security/portal_security.xml +++ b/addons/portal_project_issue/security/portal_security.xml @@ -3,28 +3,27 @@ - Project/Issue: portal users: public or portal and following + Project/Issue: portal users: public or (portal and colleagues following) or (followers and following) - ['|', - ('project_id.privacy_visibility', '=', 'public'), + ['|', '|', + ('project_id.privacy_visibility', 'in', ['public']), '&', - ('project_id.privacy_visibility', 'in', ['portal', 'followers']), - '|', - ('message_follower_ids','in', [user.partner_id.id]), - ('user_id', '=', user.id), + ('project_id.privacy_visibility', '=', 'portal'), + ('message_follower_ids', 'child_of', [user.partner_id.commercial_partner_id.id]), + '&', + ('project_id.privacy_visibility', '=', 'followers'), + ('message_follower_ids', 'in', [user.partner_id.id]), ] - Project/Issue: employees: public, portal, employee or following or assigned + Project/Issue: employees: public, portal, employee or (followers and following) ['|', - ('user_id', '=', user.id), - '|', - ('project_id.privacy_visibility', 'in', ['public', 'portal', 'employees']), - '&', - ('project_id.privacy_visibility', '=', 'followers'), - ('message_follower_ids', 'in', [user.partner_id.id]), + ('project_id.privacy_visibility', 'in', ['public', 'portal', 'employees']), + '&', + ('project_id.privacy_visibility', '=', 'followers'), + ('message_follower_ids', 'in', [user.partner_id.id]), ] diff --git a/addons/portal_project_long_term/security/portal_security.xml b/addons/portal_project_long_term/security/portal_security.xml index eab70ebe734..d8aec542847 100644 --- a/addons/portal_project_long_term/security/portal_security.xml +++ b/addons/portal_project_long_term/security/portal_security.xml @@ -3,16 +3,9 @@ - Project/Phase: portal users: public or portal and following + Project/Phase: portal users: public or (portal and colleagues following) or (followers and following) - ['|', - ('project_id.privacy_visibility', '=', 'public'), - '&', - ('project_id.privacy_visibility', 'in', ['portal', 'followers']), - '|', - ('message_follower_ids','in', [user.partner_id.id]), - ('user_id', '=', user.id), - ] + [('project_id.privacy_visibility', 'in', ['public', 'portal'])] diff --git a/addons/portal_sale/portal_sale.py b/addons/portal_sale/portal_sale.py index cd3b702d3c5..07300c5d463 100644 --- a/addons/portal_sale/portal_sale.py +++ b/addons/portal_sale/portal_sale.py @@ -104,25 +104,6 @@ class account_invoice(osv.Model): pass return action_dict - def invoice_validate(self, cr, uid, ids, context=None): - # fetch the partner's id and subscribe the partner to the invoice - document = self.browse(cr, uid, ids[0], context=context) - partner = document.partner_id - # TDE note: this code should be improved: used a real invite wizard instead of an ugly email - if partner.id not in document.message_follower_ids: - self.message_subscribe(cr, uid, ids, [partner.id], context=context) - mail_values = { - 'recipient_ids': [(4, partner.id)], - 'subject': 'Invitation to follow %s' % document.name_get()[0][1], - 'body_html': 'You have been invited to follow %s' % document.name_get()[0][1], - 'auto_delete': True, - 'type': 'email', - } - mail_obj = self.pool.get('mail.mail') - mail_id = mail_obj.create(cr, uid, mail_values, context=context) - mail_obj.send(cr, uid, [mail_id], context=context) - return super(account_invoice, self).invoice_validate(cr, uid, ids, context=context) - def get_signup_url(self, cr, uid, ids, context=None): assert len(ids) == 1 document = self.browse(cr, uid, ids[0], context=context) diff --git a/addons/product/report/product_label.xsl b/addons/product/report/product_label.xsl index 641db73ea7d..5dbb2d64a28 100644 --- a/addons/product/report/product_label.xsl +++ b/addons/product/report/product_label.xsl @@ -67,7 +67,7 @@ - + diff --git a/addons/project/project.py b/addons/project/project.py index 8d7f09f8c4e..5d5abce3066 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -198,8 +198,12 @@ class project(osv.osv): return res def _task_count(self, cr, uid, ids, field_name, arg, context=None): + if context is None: + context = {} res = dict.fromkeys(ids, 0) - task_ids = self.pool.get('project.task').search(cr, uid, [('project_id', 'in', ids)]) + ctx = context.copy() + ctx['active_test'] = False + task_ids = self.pool.get('project.task').search(cr, uid, [('project_id', 'in', ids)], context=ctx) for task in self.pool.get('project.task').browse(cr, uid, task_ids, context): res[task.project_id.id] += 1 return res @@ -210,7 +214,7 @@ class project(osv.osv): def _get_visibility_selection(self, cr, uid, context=None): """ Overriden in portal_project to offer more options """ - return [('public', 'All Users'), + return [('public', 'Public'), ('employees', 'Employees Only'), ('followers', 'Followers Only')] @@ -275,7 +279,17 @@ class project(osv.osv): "with Tasks (or optionally Issues if the Issue Tracker module is installed)."), 'alias_model': fields.selection(_alias_models, "Alias Model", select=True, required=True, help="The kind of document created when an email is received on this project's email alias"), - 'privacy_visibility': fields.selection(_visibility_selection, 'Privacy / Visibility', required=True), + 'privacy_visibility': fields.selection(_visibility_selection, 'Privacy / Visibility', required=True, + help="Holds visibility of the tasks or issues that belong to the current project:\n" + "- Public: everybody sees everything; if portal is activated, portal users\n" + " see all tasks or issues; if anonymous portal is activated, visitors\n" + " see all tasks or issues\n" + "- Portal (only available if Portal is installed): employees see everything;\n" + " if portal is activated, portal users see the tasks or issues followed by\n" + " them or by someone of their company\n" + "- Employees Only: employees see all tasks or issues\n" + "- Followers Only: employees see only the followed tasks or issues; if portal\n" + " is activated, portal users see the followed tasks or issues."), 'state': fields.selection([('template', 'Template'),('draft','New'),('open','In Progress'), ('cancelled', 'Cancelled'),('pending','Pending'),('close','Closed')], 'Status', required=True,), 'doc_count':fields.function(_get_attached_docs, string="Number of documents attached", type='int') } @@ -293,7 +307,7 @@ class project(osv.osv): 'sequence': 10, 'type_ids': _get_type_common, 'alias_model': 'project.task', - 'privacy_visibility': 'public', + 'privacy_visibility': 'employees', } # TODO: Why not using a SQL contraints ? @@ -612,7 +626,8 @@ class task(base_stage, osv.osv): search_domain = [] project_id = self._resolve_project_id_from_context(cr, uid, context=context) if project_id: - search_domain += [('project_ids', '=', project_id)] + search_domain += ['|', ('project_ids', '=', project_id)] + search_domain += [('id', 'in', ids)] stage_ids = stage_obj._search(cr, uid, search_domain, order=order, access_rights_uid=access_rights_uid, context=context) result = stage_obj.name_get(cr, access_rights_uid, stage_ids, context=context) # restore order of the search diff --git a/addons/project/project_demo.xml b/addons/project/project_demo.xml index f5fbf878fd0..b7dcc2bdb83 100644 --- a/addons/project/project_demo.xml +++ b/addons/project/project_demo.xml @@ -62,7 +62,7 @@ E-Learning Integration project.task - public + employees
@@ -76,6 +76,7 @@ Website Design Templates project.task + employees @@ -89,6 +90,7 @@ Data Import/Export Plugin project.task + followers diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml index 298355d4c82..eb042e5f0c7 100644 --- a/addons/project/project_view.xml +++ b/addons/project/project_view.xml @@ -52,7 +52,8 @@ kanban,tree,form,calendar,gantt,graph { 'search_default_project_id': [active_id], - 'default_project_id': active_id, + 'default_project_id': active_id, + 'active_test': False, } @@ -509,6 +510,7 @@
  • !
  • +
    diff --git a/addons/project/security/project_security.xml b/addons/project/security/project_security.xml index 4bbaa9b788e..e674019443b 100644 --- a/addons/project/security/project_security.xml +++ b/addons/project/security/project_security.xml @@ -75,15 +75,13 @@ - Project/Task: employees: public or employee or following or assigned + Project/Task: employees: public or employee or (followers and following) ['|', - ('user_id', '=', user.id), - '|', - ('project_id.privacy_visibility', 'in', ['public', 'employees']), - '&', - ('project_id.privacy_visibility', '=', 'followers'), - ('message_follower_ids', 'in', [user.partner_id.id]), + ('project_id.privacy_visibility', 'in', ['public', 'employees']), + '&', + ('project_id.privacy_visibility', '=', 'followers'), + ('message_follower_ids', 'in', [user.partner_id.id]), ] diff --git a/addons/project_gtd/project_gtd_view.xml b/addons/project_gtd/project_gtd_view.xml index 1467ce55fab..4bfd5b783c7 100644 --- a/addons/project_gtd/project_gtd_view.xml +++ b/addons/project_gtd/project_gtd_view.xml @@ -106,6 +106,8 @@ + + diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py index 517d335aa48..a008c670138 100644 --- a/addons/project_issue/project_issue.py +++ b/addons/project_issue/project_issue.py @@ -495,10 +495,10 @@ class project_issue(base_stage, osv.osv): def message_get_suggested_recipients(self, cr, uid, ids, context=None): recipients = super(project_issue, self).message_get_suggested_recipients(cr, uid, ids, context=context) for issue in self.browse(cr, uid, ids, context=context): - if issue.partner_id: - self._message_add_suggested_recipient(cr, uid, recipients, issue, partner=issue.partner_id, reason=_('Customer')) - elif issue.email_from: + if issue.email_from: self._message_add_suggested_recipient(cr, uid, recipients, issue, email=issue.email_from, reason=_('Customer Email')) + elif issue.partner_id: + self._message_add_suggested_recipient(cr, uid, recipients, issue, partner=issue.partner_id, reason=_('Customer')) return recipients def message_new(self, cr, uid, msg, custom_values=None, context=None): diff --git a/addons/project_issue/security/project_issue_security.xml b/addons/project_issue/security/project_issue_security.xml index 5215a94a8b7..c8ed12086e4 100644 --- a/addons/project_issue/security/project_issue_security.xml +++ b/addons/project_issue/security/project_issue_security.xml @@ -10,15 +10,13 @@ - Project/Issue: employees: public or employee or following or assigned + Project/Issue: employees: public or employee or (followers and following) ['|', - '|', - ('project_id.privacy_visibility', 'in', ['public', 'employees']), - '&', - ('project_id.privacy_visibility', '=', 'followers'), - ('message_follower_ids', 'in', [user.id]), - ('user_id', '=', user.id), + ('project_id.privacy_visibility', 'in', ['public', 'employees']), + '&', + ('project_id.privacy_visibility', '=', 'followers'), + ('message_follower_ids', 'in', [user.id]), ] diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 26e34048b40..849e558563a 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -640,7 +640,7 @@ class purchase_order(osv.osv): 'product_uom': order_line.product_uom.id, 'product_uos': order_line.product_uom.id, 'date': self.date_to_datetime(cr, uid, order.date_order, context), - 'date_expected': self.date_to_datetime(cr, uid, order.date_order, context), + 'date_expected': self.date_to_datetime(cr, uid, order_line.date_planned, context), 'location_id': order.partner_id.property_stock_supplier.id, 'location_dest_id': order.location_id.id, 'picking_id': picking_id, @@ -952,7 +952,8 @@ class purchase_order_line(osv.osv): lang = res_partner.browse(cr, uid, partner_id).lang context_partner.update( {'lang': lang, 'partner_id': partner_id} ) product = product_product.browse(cr, uid, product_id, context=context_partner) - name = product.name + #call name_get() with partner in the context to eventually match name and description in the seller_ids field + dummy, name = product_product.name_get(cr, uid, product_id, context=context_partner)[0] if product.description_purchase: name += '\n' + product.description_purchase res['value'].update({'name': name}) diff --git a/addons/purchase_double_validation/test/purchase_double_validation_test.yml b/addons/purchase_double_validation/test/purchase_double_validation_test.yml old mode 100755 new mode 100644 diff --git a/addons/purchase_requisition/test/purchase_requisition_demo.yml b/addons/purchase_requisition/test/purchase_requisition_demo.yml old mode 100755 new mode 100644 diff --git a/addons/report_webkit/__init__.py b/addons/report_webkit/__init__.py index 2c23fd8ed90..e00289407d8 100644 --- a/addons/report_webkit/__init__.py +++ b/addons/report_webkit/__init__.py @@ -25,7 +25,7 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # ############################################################################## diff --git a/addons/report_webkit/__openerp__.py b/addons/report_webkit/__openerp__.py index b962669eee9..f4035a951de 100644 --- a/addons/report_webkit/__openerp__.py +++ b/addons/report_webkit/__openerp__.py @@ -25,7 +25,7 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # ############################################################################## diff --git a/addons/report_webkit/company.py b/addons/report_webkit/company.py index f9ae4191528..b29354938de 100644 --- a/addons/report_webkit/company.py +++ b/addons/report_webkit/company.py @@ -25,7 +25,7 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # ############################################################################## diff --git a/addons/report_webkit/convert.py b/addons/report_webkit/convert.py index b4d42325bb6..e30209a77dc 100644 --- a/addons/report_webkit/convert.py +++ b/addons/report_webkit/convert.py @@ -25,7 +25,7 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # ############################################################################## diff --git a/addons/report_webkit/header.py b/addons/report_webkit/header.py index 9713efc5382..7a290662498 100644 --- a/addons/report_webkit/header.py +++ b/addons/report_webkit/header.py @@ -25,7 +25,7 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # ############################################################################## diff --git a/addons/report_webkit/ir_report.py b/addons/report_webkit/ir_report.py index 4b64a54c420..cea2b4e8329 100644 --- a/addons/report_webkit/ir_report.py +++ b/addons/report_webkit/ir_report.py @@ -25,7 +25,7 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # ############################################################################## diff --git a/addons/report_webkit/report_helper.py b/addons/report_webkit/report_helper.py index af9408b834e..83286dc59bd 100644 --- a/addons/report_webkit/report_helper.py +++ b/addons/report_webkit/report_helper.py @@ -25,7 +25,7 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # ############################################################################## diff --git a/addons/report_webkit/webkit_report.py b/addons/report_webkit/webkit_report.py index 3d8e41c42ff..82061daa758 100644 --- a/addons/report_webkit/webkit_report.py +++ b/addons/report_webkit/webkit_report.py @@ -26,7 +26,7 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # ############################################################################## diff --git a/addons/report_webkit/wizard/__init__.py b/addons/report_webkit/wizard/__init__.py index e8ae8b79fc0..e95244cc7aa 100644 --- a/addons/report_webkit/wizard/__init__.py +++ b/addons/report_webkit/wizard/__init__.py @@ -25,7 +25,7 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # ############################################################################## diff --git a/addons/report_webkit/wizard/report_webkit_actions.py b/addons/report_webkit/wizard/report_webkit_actions.py index 5f91d05d671..e22e7948d59 100644 --- a/addons/report_webkit/wizard/report_webkit_actions.py +++ b/addons/report_webkit/wizard/report_webkit_actions.py @@ -25,7 +25,7 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # ############################################################################## diff --git a/addons/resource/faces/observer.py b/addons/resource/faces/observer.py index 894345230ea..28ae58eb2b6 100644 --- a/addons/resource/faces/observer.py +++ b/addons/resource/faces/observer.py @@ -22,7 +22,7 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, write to the # Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ############################################################################ #@-node:<< Copyright >> diff --git a/addons/resource/faces/pcalendar.py b/addons/resource/faces/pcalendar.py index c82c49d4816..24c974233d8 100644 --- a/addons/resource/faces/pcalendar.py +++ b/addons/resource/faces/pcalendar.py @@ -22,7 +22,7 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, write to the # Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ############################################################################ #@-node:<< Copyright >> diff --git a/addons/resource/faces/plocale.py b/addons/resource/faces/plocale.py index 61bfa91917b..908fd1252e9 100644 --- a/addons/resource/faces/plocale.py +++ b/addons/resource/faces/plocale.py @@ -17,7 +17,7 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, write to the # Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ############################################################################ import gettext diff --git a/addons/resource/faces/resource.py b/addons/resource/faces/resource.py index 3451806444e..faee8174994 100644 --- a/addons/resource/faces/resource.py +++ b/addons/resource/faces/resource.py @@ -22,7 +22,7 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, write to the # Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ############################################################################ #@-node:<< Copyright >> diff --git a/addons/resource/faces/task.py b/addons/resource/faces/task.py index 7516f41db2a..961f6213d1d 100644 --- a/addons/resource/faces/task.py +++ b/addons/resource/faces/task.py @@ -22,7 +22,7 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, write to the # Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ############################################################################ #@-node:<< Copyright >> diff --git a/addons/resource/faces/timescale.py b/addons/resource/faces/timescale.py index 3e7c3c1dc89..818c031b7d5 100644 --- a/addons/resource/faces/timescale.py +++ b/addons/resource/faces/timescale.py @@ -17,7 +17,7 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, write to the # Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ############################################################################ import faces.pcalendar as pcal diff --git a/addons/resource/faces/utils.py b/addons/resource/faces/utils.py index 54985767613..6568c314fb5 100644 --- a/addons/resource/faces/utils.py +++ b/addons/resource/faces/utils.py @@ -17,7 +17,7 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, write to the # Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ############################################################################ import observer diff --git a/addons/resource/resource.py b/addons/resource/resource.py index 944c90a3749..449fa422ab4 100644 --- a/addons/resource/resource.py +++ b/addons/resource/resource.py @@ -25,6 +25,7 @@ from dateutil import rrule import math from faces import * from openerp.osv import fields, osv +from openerp.tools.float_utils import float_compare from openerp.tools.translate import _ from itertools import groupby @@ -108,11 +109,11 @@ class resource_calendar(osv.osv): result = [] maxrecur = 100 current_hour = dt_from.hour - while (todo>0) and maxrecur: + while float_compare(todo, 0, 4) and maxrecur: cr.execute("select hour_from,hour_to from resource_calendar_attendance where dayofweek='%s' and calendar_id=%s order by hour_from desc", (dt_from.weekday(),id)) for (hour_from,hour_to) in cr.fetchall(): leave_flag = False - if (hour_from0): + if (hour_fromtodo: hour_from = m-todo @@ -161,10 +162,10 @@ class resource_calendar(osv.osv): result = [] maxrecur = 100 current_hour = dt_from.hour - while (todo>0) and maxrecur: + while float_compare(todo, 0, 4) and maxrecur: for (hour_from,hour_to) in [(item['hour_from'], item['hour_to']) for item in hours_by_cal[id] if item['dayofweek'] == str(dt_from.weekday())]: leave_flag = False - if (hour_to>current_hour) and (todo>0): + if (hour_to>current_hour) and float_compare(todo, 0, 4): m = max(hour_from, current_hour) if (hour_to-m)>todo: hour_to = m+todo diff --git a/addons/sale/res_partner_view.xml b/addons/sale/res_partner_view.xml index 40ac119fdee..5107f0c17af 100644 --- a/addons/sale/res_partner_view.xml +++ b/addons/sale/res_partner_view.xml @@ -69,27 +69,15 @@ False sale.group_delivery_invoice_address - + + False sale.group_delivery_invoice_address - - False - sale.group_delivery_invoice_address - - - False - sale.group_delivery_invoice_address - - - False - sale.group_delivery_invoice_address - - - False - sale.group_delivery_invoice_address - - + False sale.group_delivery_invoice_address diff --git a/addons/sale/wizard/sale_line_invoice.py b/addons/sale/wizard/sale_line_invoice.py index 83b953cc4d5..3b04319f5c7 100644 --- a/addons/sale/wizard/sale_line_invoice.py +++ b/addons/sale/wizard/sale_line_invoice.py @@ -21,6 +21,7 @@ from openerp.osv import osv, fields from openerp.tools.translate import _ +from openerp import netsvc class sale_order_line_make_invoice(osv.osv_memory): _name = "sale.order.line.make.invoice" @@ -80,6 +81,7 @@ class sale_order_line_make_invoice(osv.osv_memory): sales_order_line_obj = self.pool.get('sale.order.line') sales_order_obj = self.pool.get('sale.order') + wf_service = netsvc.LocalService('workflow') for line in sales_order_line_obj.browse(cr, uid, context.get('active_ids', []), context=context): if (not line.invoiced) and (line.state not in ('draft', 'cancel')): if not line.order_id in invoices: diff --git a/addons/sale_analytic_plans/sale_analytic_plans_view.xml b/addons/sale_analytic_plans/sale_analytic_plans_view.xml index 3600d71b7d4..121efbdf12e 100644 --- a/addons/sale_analytic_plans/sale_analytic_plans_view.xml +++ b/addons/sale_analytic_plans/sale_analytic_plans_view.xml @@ -52,5 +52,17 @@ + + account.invoice.form.analytic.inherit + account.invoice + + + + + + + + + diff --git a/addons/sale_crm/sale_crm.py b/addons/sale_crm/sale_crm.py index d0899729050..3172999c545 100644 --- a/addons/sale_crm/sale_crm.py +++ b/addons/sale_crm/sale_crm.py @@ -31,6 +31,12 @@ class sale_order(osv.osv): domain="['|',('section_id','=',section_id),('section_id','=',False), ('object_id.model', '=', 'crm.lead')]") } + def _prepare_invoice(self, cr, uid, order, lines, context=None): + invoice_vals = super(sale_order, self)._prepare_invoice(cr, uid, order, lines, context=context) + if order.section_id and order.section_id.id: + invoice_vals['section_id'] = order.section_id.id + return invoice_vals + class crm_case_section(osv.osv): _inherit = 'crm.case.section' diff --git a/addons/sale_crm/sale_crm_view.xml b/addons/sale_crm/sale_crm_view.xml index f8b4228334e..31c0317969a 100644 --- a/addons/sale_crm/sale_crm_view.xml +++ b/addons/sale_crm/sale_crm_view.xml @@ -16,6 +16,11 @@ + + + {'stage_type': 'opportunity', 'default_type': 'opportunity', 'default_user_id': uid, 'needaction_menu_ref': 'sale.menu_sale_quotations'} + + sale.order.inherit sale.order @@ -110,7 +115,7 @@ - + diff --git a/addons/sale_stock/stock_view.xml b/addons/sale_stock/stock_view.xml index d06526902fd..0f5b9c4f1e6 100644 --- a/addons/sale_stock/stock_view.xml +++ b/addons/sale_stock/stock_view.xml @@ -1,16 +1,6 @@ - - stock.picking.form - stock.picking - - - - - - - stock.move.form @@ -51,7 +41,7 @@ Outgoing picking Inherited - stock.picking + stock.picking.out diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 764d9de453e..db73bae3b6c 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -29,7 +29,7 @@ from openerp.osv import fields, osv from openerp.tools.translate import _ from openerp import netsvc from openerp import tools -from openerp.tools import float_compare +from openerp.tools import float_compare, DEFAULT_SERVER_DATETIME_FORMAT import openerp.addons.decimal_precision as dp import logging _logger = logging.getLogger(__name__) @@ -647,7 +647,7 @@ class stock_picking(osv.osv): ), 'min_date': fields.function(get_min_max_date, fnct_inv=_set_minimum_date, multi="min_max_date", store=True, type='datetime', string='Scheduled Time', select=1, help="Scheduled time for the shipment to be processed"), - 'date': fields.datetime('Time', help="Creation time, usually the time of the order.", select=True, states={'done':[('readonly', True)], 'cancel':[('readonly',True)]}), + 'date': fields.datetime('Creation Date', help="Creation date, usually the time of the order.", select=True, states={'done':[('readonly', True)], 'cancel':[('readonly',True)]}), 'date_done': fields.datetime('Date of Transfer', help="Date of Completion", states={'done':[('readonly', True)], 'cancel':[('readonly',True)]}), 'max_date': fields.function(get_min_max_date, fnct_inv=_set_maximum_date, multi="min_max_date", store=True, type='datetime', string='Max. Expected Date', select=2), @@ -2323,7 +2323,6 @@ class stock_move(osv.osv): 'line_id': move_lines, 'ref': move.picking_id and move.picking_id.name}) - def action_done(self, cr, uid, ids, context=None): """ Makes the move done and if all moves are done, it will finish the picking. @return: @@ -2369,7 +2368,7 @@ class stock_move(osv.osv): if todo: self.action_confirm(cr, uid, todo, context=context) - self.write(cr, uid, move_ids, {'state': 'done', 'date': time.strftime('%Y-%m-%d %H:%M:%S')}, context=context) + self.write(cr, uid, move_ids, {'state': 'done', 'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)}, context=context) for id in move_ids: wf_service.trg_trigger(uid, 'stock.move', id, cr) @@ -2412,14 +2411,14 @@ class stock_move(osv.osv): # or if it's the same as that of the secondary amount being posted. account_obj = self.pool.get('account.account') src_acct, dest_acct = account_obj.browse(cr, uid, [src_account_id, dest_account_id], context=context) - src_main_currency_id = src_acct.company_id.currency_id.id - dest_main_currency_id = dest_acct.company_id.currency_id.id + src_main_currency_id = src_acct.currency_id and src_acct.currency_id.id or src_acct.company_id.currency_id.id + dest_main_currency_id = dest_acct.currency_id and dest_acct.currency_id.id or dest_acct.company_id.currency_id.id cur_obj = self.pool.get('res.currency') if reference_currency_id != src_main_currency_id: # fix credit line: credit_line_vals['credit'] = cur_obj.compute(cr, uid, reference_currency_id, src_main_currency_id, reference_amount, context=context) if (not src_acct.currency_id) or src_acct.currency_id.id == reference_currency_id: - credit_line_vals.update(currency_id=reference_currency_id, amount_currency=reference_amount) + credit_line_vals.update(currency_id=reference_currency_id, amount_currency=-reference_amount) if reference_currency_id != dest_main_currency_id: # fix debit line: debit_line_vals['debit'] = cur_obj.compute(cr, uid, reference_currency_id, dest_main_currency_id, reference_amount, context=context) diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index 6097885175b..b1a1fa048be 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -1262,8 +1262,8 @@ - - + + diff --git a/addons/web_shortcuts/static/src/css/web_shortcuts.css b/addons/web_shortcuts/static/src/css/web_shortcuts.css index 8424e146d06..5d4e34f53b9 100644 --- a/addons/web_shortcuts/static/src/css/web_shortcuts.css +++ b/addons/web_shortcuts/static/src/css/web_shortcuts.css @@ -54,4 +54,7 @@ border-left: none; padding-left: 0; } - +.oe_systray_shortcuts_items > li > a:hover { + overflow:visible; + white-space: normal; +} \ No newline at end of file