[FORWARD] Forward port of 7.0 branch until revision 9143.
authorThibault Delavallée <tde@openerp.com>
Tue, 21 May 2013 12:23:59 +0000 (14:23 +0200)
committerThibault Delavallée <tde@openerp.com>
Tue, 21 May 2013 12:23:59 +0000 (14:23 +0200)
bzr revid: tde@openerp.com-20130521122359-b5vii7gv8arluz06

40 files changed:
1  2 
addons/account/account_invoice.py
addons/account/wizard/pos_box.py
addons/account_asset/wizard/account_asset_change_duration.py
addons/account_asset/wizard/wizard_asset_compute.py
addons/account_followup/account_followup.py
addons/account_test/account_test.py
addons/account_voucher/account_voucher.py
addons/account_voucher/invoice.py
addons/account_voucher/test/case4_cad_chf.yml
addons/anonymization/anonymization.py
addons/auth_openid/res_users.py
addons/document_webdav/webdav_server.py
addons/hr_recruitment/hr_recruitment.py
addons/hr_timesheet_sheet/hr_timesheet_sheet.py
addons/hr_timesheet_sheet/test/test_hr_timesheet_sheet.yml
addons/l10n_fr/wizard/fr_report_bilan.py
addons/l10n_fr/wizard/fr_report_compute_resultant.py
addons/l10n_ro/res_partner.py
addons/mail/mail_alias.py
addons/mail/mail_followers.py
addons/mail/mail_mail.py
addons/mail/mail_thread.py
addons/mail/static/src/js/mail.js
addons/point_of_sale/wizard/pos_box.py
addons/point_of_sale/wizard/pos_session_opening.py
addons/portal/tests/test_portal.py
addons/project/project.py
addons/project/project_view.xml
addons/purchase/purchase.py
addons/report_webkit/__init__.py
addons/report_webkit/__openerp__.py
addons/report_webkit/header.py
addons/report_webkit/ir_report.py
addons/report_webkit/report_helper.py
addons/report_webkit/webkit_report.py
addons/report_webkit/wizard/report_webkit_actions.py
addons/resource/resource.py
addons/sale_crm/sale_crm.py
addons/stock/stock.py
addons/stock/stock_view.xml

@@@ -985,10 -981,12 +986,11 @@@ class account_invoice(osv.osv)
                  'line_id': line,
                  'journal_id': journal_id,
                  'date': date,
-                 'narration':inv.comment
+                 'narration': inv.comment,
+                 'company_id': inv.company_id.id,
              }
              period_id = inv.period_id and inv.period_id.id or False
 -            ctx.update(company_id=inv.company_id.id,
 -                       account_period_prefer_normal=True)
 +            ctx.update(company_id=inv.company_id.id)
              if not period_id:
                  period_ids = period_obj.find(cr, uid, inv.date_invoice, context=ctx)
                  period_id = period_ids and period_ids[0] or False
Simple merge
Simple merge
Simple merge
@@@ -543,7 -543,8 +543,8 @@@ class ir_model_fields_anonymize_wizard(
              fixes = group(fixes, ('model_name', 'field_name'))
  
              for line in data:
+                 queries = []
 -                table_name = self.pool.get(line['model_id'])._table if self.pool.get(line['model_id']) else None
 +                table_name = self.pool[line['model_id']]._table if line['model_id'] in self.pool else None
  
                  # check if custom sql exists:
                  key = (line['model_id'], line['field_id'])
Simple merge
@@@ -510,9 -503,11 +510,12 @@@ class hr_job(osv.osv)
  
      def _auto_init(self, cr, context=None):
          """Installation hook to create aliases for all jobs and avoid constraint errors."""
-         res = self.pool.get('mail.alias').migrate_to_alias(cr, self._name, self._table, super(hr_job,self)._auto_init,
-             self._columns['alias_id'], 'name', alias_prefix='job+', alias_defaults={'job_id': 'id'}, context=context)
+         if context is None:
+             context = {}
+         alias_context = dict(context, alias_model_name='hr.applicant')
 -        self.pool.get('mail.alias').migrate_to_alias(cr, self._name, self._table, super(hr_job, self)._auto_init,
++        res = self.pool.get('mail.alias').migrate_to_alias(cr, self._name, self._table, super(hr_job, self)._auto_init,
+             self._columns['alias_id'], 'name', alias_prefix='job+', alias_defaults={'job_id': 'id'}, context=alias_context)
 +        return res
  
      def create(self, cr, uid, vals, context=None):
          mail_alias = self.pool.get('mail.alias')
    if the difference between Timesheet hour and attendance hour is more than 1 hour it will give message.
  -
    !python {model: hr_timesheet_sheet.sheet}: |
 -        uid = ref('base.user_root')
 -        import netsvc
 -        try:
 -            self.button_confirm(cr, uid, [ref('hr_timesheet_sheet_sheet_deddk0')], {"active_ids":
 -              [ref("hr_timesheet_sheet.menu_act_hr_timesheet_sheet_form")],"active_id": ref("hr_timesheet_sheet.menu_act_hr_timesheet_sheet_form"),
 -              })
 -            assert True, "The validation of the timesheet was unexpectedly accepted despite the 2:30 hours of difference"
 -        except:
 -            pass
 +    uid = ref('base.user_root')
++    from openerp import netsvc
 +    try:
 +        self.button_confirm(cr, uid, [ref('hr_timesheet_sheet_sheet_deddk0')], {"active_ids":
 +          [ref("hr_timesheet_sheet.menu_act_hr_timesheet_sheet_form")],"active_id": ref("hr_timesheet_sheet.menu_act_hr_timesheet_sheet_form"),
 +          })
++        assert True, "The validation of the timesheet was unexpectedly accepted despite the 2:30 hours of difference"
 +    except:
 +        pass
  -
    I Modified the timesheet record and make the difference less than 1 hour.
  -
@@@ -164,15 -161,15 +166,15 @@@ class mail_alias(osv.Model)
  
          registry = RegistryManager.get(cr.dbname)
          mail_alias = registry.get('mail.alias')
 -        child_class_model = registry.get(child_model_name)
 +        child_class_model = registry[child_model_name]
-         no_alias_ids = child_class_model.search(cr, SUPERUSER_ID, [('alias_id', '=', False)], context={'active_test':False})
+         no_alias_ids = child_class_model.search(cr, SUPERUSER_ID, [('alias_id', '=', False)], context={'active_test': False})
          # Use read() not browse(), to avoid prefetching uninitialized inherited fields
          for obj_data in child_class_model.read(cr, SUPERUSER_ID, no_alias_ids, [alias_key]):
-             alias_vals = {'alias_name': '%s%s' % (alias_prefix, obj_data[alias_key]) }
+             alias_vals = {'alias_name': '%s%s' % (alias_prefix, obj_data[alias_key])}
              if alias_force_key:
                  alias_vals['alias_force_thread_id'] = obj_data[alias_force_key]
-             alias_vals['alias_defaults'] = dict( (k, obj_data[v]) for k, v in alias_defaults.iteritems())
-             alias_id = mail_alias.create_unique_alias(cr, SUPERUSER_ID, alias_vals, model_name=child_model_name)
+             alias_vals['alias_defaults'] = dict((k, obj_data[v]) for k, v in alias_defaults.iteritems())
+             alias_id = mail_alias.create_unique_alias(cr, SUPERUSER_ID, alias_vals, model_name=context.get('alias_model_name', child_model_name))
              child_class_model.write(cr, SUPERUSER_ID, obj_data['id'], {'alias_id': alias_id})
              _logger.info('Mail alias created for %s %s (uid %s)', child_model_name, obj_data[alias_key], obj_data['id'])
  
Simple merge
@@@ -202,16 -157,21 +202,18 @@@ class mail_mail(osv.Model)
              :param browse_record mail: mail.mail browse_record
              :param browse_record partner: specific recipient partner
          """
-         if force or (not mail.subject and mail.model and mail.res_id):
+         if (force or not mail.subject) and mail.record_name:
              return 'Re: %s' % (mail.record_name)
+         elif (force or not mail.subject) and mail.parent_id and mail.parent_id.subject:
+             return 'Re: %s' % (mail.parent_id.subject)
          return mail.subject
  
 -    def send_get_mail_body(self, cr, uid, mail, partner=None, context=None):
 -        """ Return a specific ir_email body. The main purpose of this method
 -            is to be inherited by Portal, to add a link for signing in, in
 +    def send_get_mail_body_footer(self, cr, uid, mail, partner=None, context=None):
 +        """ Return a specific footer for the ir_email body.  The main purpose of this method
 +            is to be inherited by Portal, to add modify the link for signing in, in
              each notification email a partner receives.
 -
 -            :param browse_record mail: mail.mail browse_record
 -            :param browse_record partner: specific recipient partner
          """
 -        body = mail.body_html
 +        body_footer = ""
          # partner is a user, link to a related document (incentive to install portal)
          if partner and 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):
Simple merge
Simple merge
@@@ -1,5 -1,5 +1,4 @@@
- #!/usr/bin/env python
  
 -from openerp import netsvc
  from openerp.osv import osv, fields
  from openerp.tools.translate import _
  
@@@ -124,9 -126,34 +126,34 @@@ class test_portal(TestMailBase)
          # Test: (pretend to) send email and check subject, body
          self.assertEqual(len(self._build_email_kwargs_list), 1, 'sent email number incorrect, should be only for Bert')
          for sent_email in self._build_email_kwargs_list:
 -            self.assertEqual(sent_email.get('subject'), 'Invitation to follow Pigs',
 -                             'subject of invitation email is incorrect')
 -            self.assertTrue('You have been invited to follow Pigs' in sent_email.get('body'),
 -                            'body of invitation email is incorrect')
 +            self.assertEqual(sent_email.get('subject'), 'Invitation to follow Discussion group: Pigs',
 +                            'invite: subject of invitation email is incorrect')
 +            self.assertIn('Administrator invited you to follow Discussion group document: Pigs', sent_email.get('body'),
 +                            'invite: body of invitation email is incorrect')
              self.assertTrue(partner_carine.signup_url in sent_email.get('body'),
 -                            'body of invitation email does not contain signup url')
 +                            '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'])
Simple merge
              <field name="name">Tasks</field>
              <field name="res_model">project.task</field>
              <field name="view_mode">kanban,tree,form,calendar,gantt,graph</field>
 -            <field name="context">{'search_default_project_id': [active_id], 'default_project_id': active_id, 'active_test': False}</field>
 +            <field name="context">{
 +                'search_default_project_id': [active_id], 
-                 'default_project_id': active_id, 
++                'default_project_id': active_id,
++                'active_test': False,
 +            }</field>
              <field name="search_view_id" ref="view_task_search_form"/>
              <field name="help" type="html">
 -              <p class="oe_view_nocontent_create">
 -                Click to create a new task.
 -              </p><p>
 -                OpenERP's project management allows you to manage the pipeline
 -                of tasks in order to get things done efficiently. You can
 -                track progress, discuss on tasks, attach documents, etc.
 -              </p>
 +                <p>
 +                    OpenERP's project management allows you to manage the pipeline
 +                    of tasks in order to get things done efficiently. You can
 +                    track progress, discuss on tasks, attach documents, etc.
 +                </p>
              </field>
          </record>
  
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -31,36 -29,13 +31,42 @@@ 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'
 +
 +    def _get_sum_month_invoice(self, cr, uid, ids, field_name, arg, context=None):
 +        res = dict.fromkeys(ids, 0)
 +        obj = self.pool.get('account.invoice.report')
 +        when = datetime.today()
 +        for section_id in ids:
 +            invoice_ids = obj.search(cr, uid, [("section_id", "=", section_id), ('state', 'not in', ['draft', 'cancel']), ('year', '=', when.year), ('month', '=', when.month > 9 and when.month or "0%s" % when.month)], context=context)
 +            for invoice in obj.browse(cr, uid, invoice_ids, context=context):
 +                res[section_id] += invoice.price_total
 +        return res
 +
 +    _columns = {
 +        'quotation_ids': fields.one2many('sale.order', 'section_id',
 +            string='Quotations', readonly=True,
 +            domain=[('state', 'in', ['draft', 'sent', 'cancel'])]),
 +        'sale_order_ids': fields.one2many('sale.order', 'section_id',
 +            string='Sale Orders', readonly=True,
 +            domain=[('state', 'not in', ['draft', 'sent', 'cancel'])]),
 +        'invoice_ids': fields.one2many('account.invoice', 'section_id',
 +            string='Invoices', readonly=True,
 +            domain=[('state', 'not in', ['draft', 'cancel'])]),
 +        'sum_month_invoice': fields.function(_get_sum_month_invoice,
 +            string='Total invoiced this month',
 +            type='integer', readonly=True),
 +    }
 +
 +
  class res_users(osv.Model):
      _inherit = 'res.users'
      _columns = {
Simple merge
Simple merge