Ejemplo n.º 1
0
    def test_onchange_specific(self):
        """ test the effect of field-specific onchange method """
        discussion = self.env.ref('test_new_api.discussion_0')
        demo = self.user_demo

        field_onchange = self.Discussion._onchange_spec()
        self.assertEqual(field_onchange.get('moderator'), '1')
        self.assertItemsEqual(
            strip_prefix('participants.', field_onchange),
            ['display_name'],
        )

        # first remove demo user from participants
        discussion.participants -= demo
        self.assertNotIn(demo, discussion.participants)

        # check that demo_user is added to participants when set as moderator
        values = {
            'name': discussion.name,
            'moderator': demo.id,
            'categories': [Command.link(cat.id) for cat in discussion.categories],
            'messages': [Command.link(msg.id) for msg in discussion.messages],
            'participants': [Command.link(usr.id) for usr in discussion.participants],
        }
        self.env.cache.invalidate()
        result = discussion.onchange(values, 'moderator', field_onchange)

        self.assertIn('participants', result['value'])
        self.assertItemsEqual(
            result['value']['participants'],
            [Command.clear()] + [Command.link(user.id) for user in discussion.participants + demo],
        )
Ejemplo n.º 2
0
    def test_50_environment(self):
        """ Test environment on records. """
        # partners and reachable records are attached to self.env
        partners = self.env['res.partner'].search([('name', 'ilike', 'j'),
                                                   ('id', 'in',
                                                    self.partners.ids)])
        self.assertEqual(partners.env, self.env)
        for x in (partners, partners[0], partners[0].company_id):
            self.assertEqual(x.env, self.env)
        for p in partners:
            self.assertEqual(p.env, self.env)

        # check that the current user can read and modify company data
        partners[0].company_id.name
        partners[0].company_id.write({'name': 'Fools'})

        # create an environment with a demo user
        demo = self.env['res.users'].create({
            'name':
            'test_environment_demo',
            'login':
            '******',
            'password':
            '******',
        })
        demo_env = self.env(user=demo)
        self.assertNotEqual(demo_env, self.env)

        # partners and related records are still attached to self.env
        self.assertEqual(partners.env, self.env)
        for x in (partners, partners[0], partners[0].company_id):
            self.assertEqual(x.env, self.env)
        for p in partners:
            self.assertEqual(p.env, self.env)

        # create record instances attached to demo_env
        demo_partners = partners.with_user(demo)
        self.assertEqual(demo_partners.env, demo_env)
        for x in (demo_partners, demo_partners[0],
                  demo_partners[0].company_id):
            self.assertEqual(x.env, demo_env)
        for p in demo_partners:
            self.assertEqual(p.env, demo_env)

        # demo user can read but not modify company data
        demo_partner = self.env['res.partner'].search([
            ('name', '=', 'Landon Roberts')
        ]).with_user(demo)
        self.assertTrue(demo_partner.company_id,
                        'This partner is supposed to be linked to a company')
        demo_partner.company_id.name
        with self.assertRaises(AccessError):
            demo_partner.company_id.write({'name': 'Pricks'})

        # remove demo user from all groups
        demo.write({'groups_id': [Command.clear()]})

        # demo user can no longer access partner data
        with self.assertRaises(AccessError):
            demo_partner.company_id.name
Ejemplo n.º 3
0
    def test_many2many(self):
        """ Test assignment of many2many field where rules apply. """
        ids = [self.id1, self.id2]

        # create container as superuser, connected to all some_objs
        container_admin = self.env['test_access_right.container'].create({'some_ids': [Command.set(ids)]})
        self.assertItemsEqual(container_admin.some_ids.ids, ids)

        # check the container as the public user
        container_user = container_admin.with_user(self.browse_ref('base.public_user'))
        container_user.invalidate_cache(['some_ids'])
        self.assertItemsEqual(container_user.some_ids.ids, [self.id1])

        # this should not fail
        container_user.write({'some_ids': [Command.set(ids)]})
        container_user.invalidate_cache(['some_ids'])
        self.assertItemsEqual(container_user.some_ids.ids, [self.id1])
        container_admin.invalidate_cache(['some_ids'])
        self.assertItemsEqual(container_admin.some_ids.ids, ids)

        # this removes all records
        container_user.write({'some_ids': [Command.clear()]})
        container_user.invalidate_cache(['some_ids'])
        self.assertItemsEqual(container_user.some_ids.ids, [])
        container_admin.invalidate_cache(['some_ids'])
        self.assertItemsEqual(container_admin.some_ids.ids, [])
Ejemplo n.º 4
0
    def test_onchange_editable_compute_one2many(self):
        # create a record with a computed editable field ('edit') on lines
        record = self.env['test_new_api.compute_editable'].create({'line_ids': [(0, 0, {'value': 7})]})
        self.env.flush_all()
        line = record.line_ids
        self.assertRecordValues(line, [{'value': 7, 'edit': 7, 'count': 0}])

        # retrieve the onchange spec for calling 'onchange'
        spec = Form(record)._view['onchange']

        # The onchange on 'line_ids' should increment 'count' and keep the value
        # of 'edit' (this field should not be recomputed), whatever the order of
        # the fields in the dictionary.  This ensures that the value set by the
        # user on a computed editable field on a line is not lost.
        line_ids = [
            Command.update(line.id, {'value': 8, 'edit': 9, 'count': 0}),
            Command.create({'value': 8, 'edit': 9, 'count': 0}),
        ]
        result = record.onchange({'line_ids': line_ids}, 'line_ids', spec)
        expected = {'value': {
            'line_ids': [
                Command.clear(),
                Command.update(line.id, {'value': 8, 'edit': 9, 'count': 8}),
                Command.create({'value': 8, 'edit': 9, 'count': 8}),
            ],
        }}
        self.assertEqual(result, expected)

        # change dict order in lines, and try again
        line_ids = [
            (op, id_, dict(reversed(list(vals.items()))))
            for op, id_, vals in line_ids
        ]
        result = record.onchange({'line_ids': line_ids}, 'line_ids', spec)
        self.assertEqual(result, expected)
Ejemplo n.º 5
0
 def test_20_crud_create(self):
     # Do: create a new record in another model
     self.action.write({
         'state':
         'object_create',
         'crud_model_id':
         self.res_country_model.id,
         'link_field_id':
         False,
         'fields_lines': [
             Command.clear(),
             Command.create({
                 'col1': self.res_country_name_field.id,
                 'value': 'record.name',
                 'evaluation_type': 'equation'
             }),
             Command.create({
                 'col1': self.res_country_code_field.id,
                 'value': 'record.name[0:2]',
                 'evaluation_type': 'equation'
             })
         ],
     })
     run_res = self.action.with_context(self.context).run()
     self.assertFalse(
         run_res,
         'ir_actions_server: create record action correctly finished should return False'
     )
     # Test: new country created
     country = self.test_country.search([('name', 'ilike', 'TestingPartner')
                                         ])
     self.assertEqual(len(country), 1, 'ir_actions_server: TODO')
     self.assertEqual(country.code, 'TE', 'ir_actions_server: TODO')
Ejemplo n.º 6
0
    def test_onchange_one2many_with_domain_on_related_field(self):
        """ test the value of the one2many field when defined with a domain on a related field"""
        discussion = self.env.ref('test_new_api.discussion_0')
        demo = self.user_demo

        # mimic UI behaviour, so we get subfields
        # (we need at least subfield: 'important_emails.important')
        view_info = self.Discussion.get_view(self.env.ref('test_new_api.discussion_form').id, 'form')
        field_onchange = self.Discussion._onchange_spec(view_info=view_info)
        self.assertEqual(field_onchange.get('messages'), '1')

        BODY = "What a beautiful day!"
        USER = self.env.user

        # create standalone email
        email = self.EmailMessage.create({
            'discussion': discussion.id,
            'name': "[%s] %s" % ('', USER.name),
            'body': BODY,
            'author': USER.id,
            'important': False,
            'email_to': demo.email,
        })

        # check if server-side cache is working correctly
        self.env.cache.invalidate()
        self.assertIn(email, discussion.emails)
        self.assertNotIn(email, discussion.important_emails)
        email.important = True
        self.assertIn(email, discussion.important_emails)

        # check that when trigger an onchange, we don't reset important emails
        # (force `invalidate` as but appear in onchange only when we get a cache
        # miss)
        self.env.cache.invalidate()
        self.assertEqual(len(discussion.messages), 4)
        values = {
            'name': "Foo Bar",
            'moderator': demo.id,
            'categories': [Command.link(cat.id) for cat in discussion.categories],
            'messages': [Command.link(msg.id) for msg in discussion.messages],
            'participants': [Command.link(usr.id) for usr in discussion.participants],
            'important_messages': [Command.link(msg.id) for msg in discussion.important_messages],
            'important_emails': [Command.link(eml.id) for eml in discussion.important_emails],
        }
        self.env.cache.invalidate()
        result = discussion.onchange(values, 'name', field_onchange)

        self.assertEqual(
            result['value']['important_emails'],
            [Command.clear(), Command.update(email.id, {
                'name': u'[Foo Bar] %s' % USER.name,
                'body': BODY,
                'author': USER.name_get()[0],
                'size': len(BODY),
                'important': True,
                'email_to': demo.email,
            })],
        )
Ejemplo n.º 7
0
    def test_08_purchases_multi_linkages(self):
        """Directly link POs to each other as 'Alternatives': check linking/unlinking
        POs that are already linked correctly work."""
        pos = []
        for _ in range(5):
            pos += self.env['purchase.order'].create({
                'partner_id':
                self.res_partner_1.id,
            }).ids
        pos = self.env['purchase.order'].browse(pos)
        po_1, po_2, po_3, po_4, po_5 = pos

        po_1.alternative_po_ids |= po_2
        po_3.alternative_po_ids |= po_4
        groups = self.env['purchase.order.group'].search([('order_ids', 'in',
                                                           pos.ids)])
        self.assertEqual(len(po_1.alternative_po_ids), 2,
                         "PO1 and PO2 should only be linked to each other")
        self.assertEqual(len(po_3.alternative_po_ids), 2,
                         "PO3 and PO4 should only be linked to each other")
        self.assertEqual(
            len(groups), 2,
            "There should only be 2 groups: (PO1,PO2) and (PO3,PO4)")

        # link non-linked PO to already linked PO
        po_5.alternative_po_ids |= po_4
        groups = self.env['purchase.order.group'].search([('order_ids', 'in',
                                                           pos.ids)])
        self.assertEqual(len(po_3.alternative_po_ids), 3,
                         "PO3 should now be linked to PO4 and PO5")
        self.assertEqual(len(po_4.alternative_po_ids), 3,
                         "PO4 should now be linked to PO3 and PO5")
        self.assertEqual(len(po_5.alternative_po_ids), 3,
                         "PO5 should now be linked to PO3 and PO4")
        self.assertEqual(
            len(groups), 2,
            "There should only be 2 groups: (PO1,PO2) and (PO3,PO4,PO5)")

        # link already linked PO to already linked PO
        po_5.alternative_po_ids |= po_1
        groups = self.env['purchase.order.group'].search([('order_ids', 'in',
                                                           pos.ids)])
        self.assertEqual(len(po_1.alternative_po_ids), 5,
                         "All 5 POs should be linked to each other now")
        self.assertEqual(
            len(groups), 1,
            "There should only be 1 group containing all 5 POs (other group should have auto-deleted"
        )

        # remove all links, make sure group auto-deletes
        (pos - po_5).alternative_po_ids = [Command.clear()]
        groups = self.env['purchase.order.group'].search([('order_ids', 'in',
                                                           pos.ids)])
        self.assertEqual(
            len(po_5.alternative_po_ids), 0,
            "Last PO should auto unlink from itself since group should have auto-deleted"
        )
        self.assertEqual(len(groups), 0, "The group should have auto-deleted")
Ejemplo n.º 8
0
    def test_write_base_one2many_with_constraint(self):
        """ Write on one2many field with lines being deleted and created. """
        rec = self.env['test_performance.base'].create({'name': 'Y'})
        rec.write({'line_ids': [Command.create({'value': val}) for val in range(12)]})

        # This write() will raise because of the unique index if the unlink() is
        # not performed before the create()
        rec.write({'line_ids': [Command.clear()] + [Command.create({'value': val}) for val in range(6)]})
        self.assertEqual(len(rec.line_ids), 6)
Ejemplo n.º 9
0
 def _compute_outbound_payment_method_line_ids(self):
     for journal in self:
         pay_method_line_ids_commands = [Command.clear()]
         if journal.type in ('bank', 'cash'):
             default_methods = journal._default_outbound_payment_methods()
             pay_method_line_ids_commands += [Command.create({
                 'name': pay_method.name,
                 'payment_method_id': pay_method.id,
             }) for pay_method in default_methods]
         journal.outbound_payment_method_line_ids = pay_method_line_ids_commands
Ejemplo n.º 10
0
 def test_name_search_with_sudo(self):
     """Check that _name_search return correct values with sudo
     """
     no_access_user = self.env['res.users'].create({
         'login': '******',
         'name': 'no_access',
         'groups_id': [Command.clear()],
     })
     document = self.env['test_access_right.ticket'].with_user(no_access_user)
     res = document.sudo().name_search('Need help here')
     #Invalide cache in case the name is already there
     #and will not trigget check_access_rights when
     #the name_get will access the name
     self.document.invalidate_cache(fnames=['name'])
     self.assertEqual(res[0][1], "Need help here")
Ejemplo n.º 11
0
    def _compute_suitable_payment_token_ids(self):
        for wizard in self:
            if wizard.can_edit_wizard and wizard.use_electronic_payment_method:
                related_partner_ids = (
                        wizard.partner_id
                        | wizard.partner_id.commercial_partner_id
                        | wizard.partner_id.commercial_partner_id.child_ids
                )._origin

                wizard.suitable_payment_token_ids = self.env['payment.token'].sudo().search([
                    ('company_id', '=', wizard.company_id.id),
                    ('acquirer_id.capture_manually', '=', False),
                    ('partner_id', 'in', related_partner_ids.ids),
                    ('acquirer_id.journal_id', '=', wizard.journal_id.id),
                ])
            else:
                wizard.suitable_payment_token_ids = [Command.clear()]
Ejemplo n.º 12
0
    def _compute_suitable_payment_token_ids(self):
        for payment in self:
            related_partner_ids = (
                payment.partner_id
                | payment.partner_id.commercial_partner_id
                | payment.partner_id.commercial_partner_id.child_ids)._origin

            if payment.use_electronic_payment_method:
                payment.suitable_payment_token_ids = self.env[
                    'payment.token'].sudo().search([
                        ('company_id', '=', payment.company_id.id),
                        ('acquirer_id.capture_manually', '=', False),
                        ('partner_id', 'in', related_partner_ids.ids),
                        ('acquirer_id.journal_id', '=', payment.journal_id.id),
                    ])
            else:
                payment.suitable_payment_token_ids = [Command.clear()]
Ejemplo n.º 13
0
 def test_01_account_tour(self):
     # Reset country and fiscal country, so that fields added by localizations are
     # hidden and non-required, and don't make the tour crash.
     # Also remove default taxes from the company and its accounts, to avoid inconsistencies
     # with empty fiscal country.
     self.env.company.write({
         'country_id': None, # Also resets account_fiscal_country_id
         'account_sale_tax_id': None,
         'account_purchase_tax_id': None,
     })
     account_with_taxes = self.env['account.account'].search([('tax_ids', '!=', False), ('company_id', '=', self.env.company.id)])
     account_with_taxes.write({
         'tax_ids': [Command.clear()],
     })
     # This tour doesn't work with demo data on runbot
     all_moves = self.env['account.move'].search([('move_type', '!=', 'entry')])
     all_moves.button_draft()
     all_moves.with_context(force_delete=True).unlink()
     self.start_tour("/web", 'account_tour', login="******")
Ejemplo n.º 14
0
 def _compute_details(self):
     for wizard in self:
         commands = [Command.clear()]
         if wizard.counter < 1 or not wizard.production_id:
             wizard.production_detailed_vals_ids = commands
             continue
         quantity = float_round(wizard.product_qty / wizard.counter, precision_rounding=wizard.product_uom_id.rounding)
         remaining_quantity = wizard.product_qty
         for _ in range(wizard.counter - 1):
             commands.append(Command.create({
                 'quantity': quantity,
                 'user_id': wizard.production_id.user_id,
                 'date': wizard.production_id.date_planned_start,
             }))
             remaining_quantity = float_round(remaining_quantity - quantity, precision_rounding=wizard.product_uom_id.rounding)
         commands.append(Command.create({
             'quantity': remaining_quantity,
             'user_id': wizard.production_id.user_id,
             'date': wizard.production_id.date_planned_start,
         }))
         wizard.production_detailed_vals_ids = commands
Ejemplo n.º 15
0
    def test_write_base_many2many(self):
        """ Write on many2many field. """
        rec1 = self.env['test_performance.base'].create({'name': 'X'})

        # create N tags on rec1: O(N) queries
        with self.assertQueryCount(4):
            rec1.invalidate_cache()
            rec1.write({'tag_ids': [Command.create({'name': 0})]})
        self.assertEqual(len(rec1.tag_ids), 1)

        with self.assertQueryCount(14):
            rec1.invalidate_cache()
            rec1.write({
                'tag_ids':
                [Command.create({'name': val}) for val in range(1, 12)]
            })
        self.assertEqual(len(rec1.tag_ids), 12)

        tags = rec1.tag_ids

        # update N tags: O(N) queries
        with self.assertQueryCount(3):
            rec1.invalidate_cache()
            rec1.write({
                'tag_ids':
                [Command.update(tag.id, {'name': 'X'}) for tag in tags[0]]
            })
        self.assertEqual(rec1.tag_ids, tags)

        with self.assertQueryCount(3):
            rec1.invalidate_cache()
            rec1.write({
                'tag_ids':
                [Command.update(tag.id, {'name': 'X'}) for tag in tags[1:]]
            })
        self.assertEqual(rec1.tag_ids, tags)

        # delete N tags: O(1) queries
        with self.assertQueryCount(__system__=8, demo=8):
            rec1.invalidate_cache()
            rec1.write(
                {'tag_ids': [Command.delete(tag.id) for tag in tags[0]]})
        self.assertEqual(rec1.tag_ids, tags[1:])

        with self.assertQueryCount(__system__=8, demo=8):
            rec1.invalidate_cache()
            rec1.write(
                {'tag_ids': [Command.delete(tag.id) for tag in tags[1:]]})
        self.assertFalse(rec1.tag_ids)
        self.assertFalse(tags.exists())

        rec1.write(
            {'tag_ids': [Command.create({'name': val}) for val in range(12)]})
        tags = rec1.tag_ids

        # unlink N tags: O(1) queries
        with self.assertQueryCount(3):
            rec1.invalidate_cache()
            rec1.write(
                {'tag_ids': [Command.unlink(tag.id) for tag in tags[0]]})
        self.assertEqual(rec1.tag_ids, tags[1:])

        with self.assertQueryCount(3):
            rec1.invalidate_cache()
            rec1.write(
                {'tag_ids': [Command.unlink(tag.id) for tag in tags[1:]]})
        self.assertFalse(rec1.tag_ids)
        self.assertTrue(tags.exists())

        rec2 = self.env['test_performance.base'].create({'name': 'X'})

        # link N tags from rec1 to rec2: O(1) queries
        with self.assertQueryCount(3):
            rec1.invalidate_cache()
            rec2.write({'tag_ids': [Command.link(tag.id) for tag in tags[0]]})
        self.assertEqual(rec2.tag_ids, tags[0])

        with self.assertQueryCount(3):
            rec1.invalidate_cache()
            rec2.write({'tag_ids': [Command.link(tag.id) for tag in tags[1:]]})
        self.assertEqual(rec2.tag_ids, tags)

        with self.assertQueryCount(2):
            rec1.invalidate_cache()
            rec2.write({'tag_ids': [Command.link(tag.id) for tag in tags[1:]]})
        self.assertEqual(rec2.tag_ids, tags)

        # empty N tags in rec2: O(1) queries
        with self.assertQueryCount(3):
            rec1.invalidate_cache()
            rec2.write({'tag_ids': [Command.clear()]})
        self.assertFalse(rec2.tag_ids)
        self.assertTrue(tags.exists())

        with self.assertQueryCount(2):
            rec1.invalidate_cache()
            rec2.write({'tag_ids': [Command.clear()]})
        self.assertFalse(rec2.tag_ids)

        # set N tags in rec2: O(1) queries
        with self.assertQueryCount(3):
            rec1.invalidate_cache()
            rec2.write({'tag_ids': [Command.set(tags.ids)]})
        self.assertEqual(rec2.tag_ids, tags)

        with self.assertQueryCount(3):
            rec1.invalidate_cache()
            rec2.write({'tag_ids': [Command.set(tags[:8].ids)]})
        self.assertEqual(rec2.tag_ids, tags[:8])

        with self.assertQueryCount(4):
            rec1.invalidate_cache()
            rec2.write({'tag_ids': [Command.set(tags[4:].ids)]})
        self.assertEqual(rec2.tag_ids, tags[4:])

        with self.assertQueryCount(3):
            rec1.invalidate_cache()
            rec2.write({'tag_ids': [Command.set(tags.ids)]})
        self.assertEqual(rec2.tag_ids, tags)

        with self.assertQueryCount(2):
            rec1.invalidate_cache()
            rec2.write({'tag_ids': [Command.set(tags.ids)]})
        self.assertEqual(rec2.tag_ids, tags)
Ejemplo n.º 16
0
    def test_write_base_one2many(self):
        """ Write on one2many field. """
        rec1 = self.env['test_performance.base'].create({'name': 'X'})

        # create N lines on rec1: O(N) queries
        with self.assertQueryCount(3):
            rec1.invalidate_cache()
            rec1.write({'line_ids': [Command.create({'value': 0})]})
        self.assertEqual(len(rec1.line_ids), 1)

        with self.assertQueryCount(15):
            rec1.invalidate_cache()
            rec1.write({
                'line_ids':
                [Command.create({'value': val}) for val in range(1, 12)]
            })
        self.assertEqual(len(rec1.line_ids), 12)

        lines = rec1.line_ids

        # update N lines: O(N) queries
        with self.assertQueryCount(6):
            rec1.invalidate_cache()
            rec1.write({
                'line_ids':
                [Command.update(line.id, {'value': 42}) for line in lines[0]]
            })
        self.assertEqual(rec1.line_ids, lines)

        with self.assertQueryCount(26):
            rec1.invalidate_cache()
            rec1.write({
                'line_ids': [
                    Command.update(line.id, {'value': 42 + line.id})
                    for line in lines[1:]
                ]
            })
        self.assertEqual(rec1.line_ids, lines)

        # delete N lines: O(1) queries
        with self.assertQueryCount(14):
            rec1.invalidate_cache()
            rec1.write(
                {'line_ids': [Command.delete(line.id) for line in lines[0]]})
        self.assertEqual(rec1.line_ids, lines[1:])

        with self.assertQueryCount(12):
            rec1.invalidate_cache()
            rec1.write(
                {'line_ids': [Command.delete(line.id) for line in lines[1:]]})
        self.assertFalse(rec1.line_ids)
        self.assertFalse(lines.exists())

        rec1.write({
            'line_ids': [Command.create({'value': val}) for val in range(12)]
        })
        lines = rec1.line_ids

        # unlink N lines: O(1) queries
        with self.assertQueryCount(14):
            rec1.invalidate_cache()
            rec1.write(
                {'line_ids': [Command.unlink(line.id) for line in lines[0]]})
        self.assertEqual(rec1.line_ids, lines[1:])

        with self.assertQueryCount(12):
            rec1.invalidate_cache()
            rec1.write(
                {'line_ids': [Command.unlink(line.id) for line in lines[1:]]})
        self.assertFalse(rec1.line_ids)
        self.assertFalse(lines.exists())

        rec1.write({
            'line_ids': [Command.create({'value': val}) for val in range(12)]
        })
        lines = rec1.line_ids
        rec2 = self.env['test_performance.base'].create({'name': 'X'})

        # link N lines from rec1 to rec2: O(1) queries
        with self.assertQueryCount(8):
            rec1.invalidate_cache()
            rec2.write(
                {'line_ids': [Command.link(line.id) for line in lines[0]]})
        self.assertEqual(rec1.line_ids, lines[1:])
        self.assertEqual(rec2.line_ids, lines[0])

        with self.assertQueryCount(8):
            rec1.invalidate_cache()
            rec2.write(
                {'line_ids': [Command.link(line.id) for line in lines[1:]]})
        self.assertFalse(rec1.line_ids)
        self.assertEqual(rec2.line_ids, lines)

        with self.assertQueryCount(4):
            rec1.invalidate_cache()
            rec2.write(
                {'line_ids': [Command.link(line.id) for line in lines[0]]})
        self.assertEqual(rec2.line_ids, lines)

        with self.assertQueryCount(4):
            rec1.invalidate_cache()
            rec2.write(
                {'line_ids': [Command.link(line.id) for line in lines[1:]]})
        self.assertEqual(rec2.line_ids, lines)

        # empty N lines in rec2: O(1) queries
        with self.assertQueryCount(13):
            rec1.invalidate_cache()
            rec2.write({'line_ids': [Command.clear()]})
        self.assertFalse(rec2.line_ids)

        with self.assertQueryCount(3):
            rec1.invalidate_cache()
            rec2.write({'line_ids': [Command.clear()]})
        self.assertFalse(rec2.line_ids)

        rec1.write({
            'line_ids': [Command.create({'value': val}) for val in range(12)]
        })
        lines = rec1.line_ids

        # set N lines in rec2: O(1) queries
        with self.assertQueryCount(8):
            rec1.invalidate_cache()
            rec2.write({'line_ids': [Command.set(lines[0].ids)]})
        self.assertEqual(rec1.line_ids, lines[1:])
        self.assertEqual(rec2.line_ids, lines[0])

        with self.assertQueryCount(6):
            rec1.invalidate_cache()
            rec2.write({'line_ids': [Command.set(lines.ids)]})
        self.assertFalse(rec1.line_ids)
        self.assertEqual(rec2.line_ids, lines)

        with self.assertQueryCount(4):
            rec1.invalidate_cache()
            rec2.write({'line_ids': [Command.set(lines.ids)]})
        self.assertEqual(rec2.line_ids, lines)
Ejemplo n.º 17
0
 def test_event_configuration_tickets_from_type(self):
     """ Test data computation (related to tickets) of event coming from its event.type template.
     This test uses pretty low level Form data checks, as manipulations in a non-saved Form are
     required to highlight an undesired behavior when switching event_type templates :
     event_ticket_ids not linked to a registration were generated and kept when switching between
     different templates in the Form, which could rapidly lead to a substantial amount of
     undesired lines. """
     # setup test records
     event_type_default = self.env['event.type'].create({
         'name': 'Type Default',
         'auto_confirm': True
     })
     event_type_tickets = self.env['event.type'].create({
         'name':
         'Type Tickets',
         'auto_confirm':
         False
     })
     event_type_tickets.write({
         'event_type_ticket_ids': [
             Command.clear(),
             Command.create({
                 'name': 'Default Ticket',
                 'seats_max': 10,
             })
         ]
     })
     event = self.env['event.event'].create({
         'name':
         'Event',
         'date_begin':
         FieldsDatetime.to_string(datetime.today() + timedelta(days=1)),
         'date_end':
         FieldsDatetime.to_string(datetime.today() + timedelta(days=15)),
         'event_type_id':
         event_type_default.id
     })
     event.write({
         'event_ticket_ids': [
             Command.clear(),
             Command.create({
                 'name': 'Registration Ticket',
                 'seats_max': 10,
             })
         ]
     })
     ticket = event.event_ticket_ids[0]
     registration = self._create_registrations(event, 1)
     # link the ticket to the registration
     registration.write({'event_ticket_id': ticket.id})
     # start test scenario
     event_form = Form(event)
     # verify that the ticket is linked to the event in the form
     self.assertEqual(
         set(
             map(lambda m: m.get('name', None),
                 event_form.event_ticket_ids._records)),
         set(['Registration Ticket']))
     # switch to an event_type with a ticket template which should be computed
     event_form.event_type_id = event_type_tickets
     # verify that both tickets are computed
     self.assertEqual(
         set(
             map(lambda m: m.get('name', None),
                 event_form.event_ticket_ids._records)),
         set(['Registration Ticket', 'Default Ticket']))
     # switch back to an event_type without default tickets
     event_form.event_type_id = event_type_default
     # verify that the ticket linked to the registration was kept, and the other removed
     self.assertEqual(
         set(
             map(lambda m: m.get('name', None),
                 event_form.event_ticket_ids._records)),
         set(['Registration Ticket']))
Ejemplo n.º 18
0
 def test_event_configuration_mails_from_type(self):
     """ Test data computation (related to mails) of event coming from its event.type template.
     This test uses pretty low level Form data checks, as manipulations in a non-saved Form are
     required to highlight an undesired behavior when switching event_type templates :
     event_mail_ids not linked to a registration were generated and kept when switching between
     different templates in the Form, which could rapidly lead to a substantial amount of
     undesired lines. """
     # setup test records
     event_type_default = self.env['event.type'].create({
         'name': 'Type Default',
         'auto_confirm': True
     })
     event_type_mails = self.env['event.type'].create({
         'name': 'Type Mails',
         'auto_confirm': False
     })
     event_type_mails.write({
         'event_type_mail_ids': [
             Command.clear(),
             Command.create({
                 'notification_type':
                 'mail',
                 'interval_nbr':
                 77,
                 'interval_unit':
                 'days',
                 'interval_type':
                 'after_event',
                 'template_ref':
                 'mail.template,%i' %
                 self.env['ir.model.data']._xmlid_to_res_id(
                     'event.event_reminder'),
             })
         ]
     })
     event = self.env['event.event'].create({
         'name':
         'Event',
         'date_begin':
         FieldsDatetime.to_string(datetime.today() + timedelta(days=1)),
         'date_end':
         FieldsDatetime.to_string(datetime.today() + timedelta(days=15)),
         'event_type_id':
         event_type_default.id
     })
     event.write({
         'event_mail_ids': [
             Command.clear(),
             Command.create({
                 'notification_type':
                 'mail',
                 'interval_unit':
                 'now',
                 'interval_type':
                 'after_sub',
                 'template_ref':
                 'mail.template,%i' %
                 self.env['ir.model.data']._xmlid_to_res_id(
                     'event.event_subscription'),
             })
         ]
     })
     mail = event.event_mail_ids[0]
     registration = self._create_registrations(event, 1)
     self.assertEqual(registration.state, 'open')  # event auto confirms
     # verify that mail is linked to the registration
     self.assertEqual(
         set(mail.mapped('mail_registration_ids.registration_id.id')),
         set([registration.id]))
     # start test scenario
     event_form = Form(event)
     # verify that mail is linked to the event in the form
     self.assertEqual(
         set(
             map(lambda m: m.get('id', None),
                 event_form.event_mail_ids._records)), set([mail.id]))
     # switch to an event_type with a mail template which should be computed
     event_form.event_type_id = event_type_mails
     # verify that 2 mails were computed
     self.assertEqual(len(event_form.event_mail_ids._records), 2)
     # verify that the mail linked to the registration was kept
     self.assertTrue(
         filter(lambda m: m.get('id', None) == mail.id,
                event_form.event_mail_ids._records))
     # since the other computed event.mail is to be created from an event.type.mail template,
     # verify that its attributes are the correct ones
     computed_mail = next(
         filter(lambda m: m.get('id', None) != mail.id,
                event_form.event_mail_ids._records), {})
     self.assertEqual(computed_mail.get('interval_nbr', None), 77)
     self.assertEqual(computed_mail.get('interval_unit', None), 'days')
     self.assertEqual(computed_mail.get('interval_type', None),
                      'after_event')
     # switch back to an event type without a mail template
     event_form.event_type_id = event_type_default
     # verify that the mail linked to the registration was kept, and the other removed
     self.assertEqual(
         set(
             map(lambda m: m.get('id', None),
                 event_form.event_mail_ids._records)), set([mail.id]))
Ejemplo n.º 19
0
    def test_event_configuration_booths_from_type(self):
        """ Test data computation (related to booths) of event coming from its event.type template. """
        # setup test records
        event_type_nobooth = self.env['event.type'].create({
            'name': 'No booth',
        })
        event_type_wbooths = self.env['event.type'].create({
            'name':
            'Using booths',
            'event_type_booth_ids': [
                Command.clear(),
                Command.create({
                    'name':
                    'Standard Booth',
                    'booth_category_id':
                    self.event_booth_category_1.id,
                }),
                Command.create({
                    'name':
                    'Premium Booth',
                    'booth_category_id':
                    self.event_booth_category_2.id,
                })
            ]
        })

        # no booth by default as no booths on type
        event = self.env['event.event'].create({
            'name':
            'Event',
            'date_begin':
            FieldsDatetime.to_string(datetime.today() + timedelta(days=1)),
            'date_end':
            FieldsDatetime.to_string(datetime.today() + timedelta(days=15)),
            'event_type_id':
            event_type_nobooth.id
        })
        self.assertEqual(event.event_booth_ids, self.env['event.booth'])

        # manually create booths: ok
        event.write({
            'event_booth_ids': [
                Command.create({
                    'name':
                    'Custom Standard Booth 1',
                    'booth_category_id':
                    self.event_booth_category_1.id,
                }),
                Command.create({
                    'name':
                    'Custom Standard Booth 2',
                    'booth_category_id':
                    self.event_booth_category_1.id,
                })
            ]
        })
        self.assertEqual(event.event_booth_count, 2)
        self.assertEqual(event.event_booth_count_available, 2)
        self.assertEqual(event.event_booth_category_ids,
                         self.event_booth_category_1)
        self.assertEqual(event.event_booth_ids[1].message_partner_ids,
                         self.env['res.partner'])

        # updating partner is independent from availability
        event.event_booth_ids[1].write({'partner_id': self.event_customer.id})
        self.assertEqual(event.event_booth_count, 2)
        self.assertEqual(event.event_booth_count_available, 2)
        self.assertEqual(event.event_booth_ids[1].message_partner_ids,
                         self.event_customer)

        # one booth is sold
        event.event_booth_ids[1].write({'state': 'unavailable'})
        self.assertEqual(event.event_booth_count, 2)
        self.assertEqual(event.event_booth_count_available, 1)

        # partner is reset: booth still unavailable but follower removed
        event.event_booth_ids[1].write({'partner_id': False})
        self.assertEqual(event.event_booth_count, 2)
        self.assertEqual(event.event_booth_count_available, 1)
        self.assertEqual(event.event_booth_ids[1].message_partner_ids,
                         self.env['res.partner'])

        # change event type to one using booths: include event type booths and keep reserved booths
        with Form(event) as event_form:
            event_form.event_type_id = event_type_wbooths
        self.assertEqual(event.event_booth_count, 3)
        self.assertEqual(
            set(r['name'] for r in event.event_booth_ids),
            set(('Custom Standard Booth 2', 'Standard Booth',
                 'Premium Booth')),
            'Should keep booths with reservation, remove unused ones and add type ones'
        )
        self.assertEqual(event.event_booth_count_available, 2)
        self.assertEqual(
            event.event_booth_category_ids,
            self.event_booth_category_1 + self.event_booth_category_2)
Ejemplo n.º 20
0
    def test_loyalty_free_product_loyalty_program(self):
        # In this program, each whiteboard pen gives 1 point.
        # 4 points can be used to get a free whiteboard pen.
        loyalty_program = self.env['loyalty.program'].create({
            'name': 'Buy 4 whiteboard_pen, Take 1 whiteboard_pen',
            'program_type': 'loyalty',
            'trigger': 'auto',
            'applies_on': 'both',
            'rule_ids': [(0, 0, {
                'product_ids': self.whiteboard_pen.ids,
                'reward_point_mode': 'unit',
                'minimum_qty': 1,
            })],
            'reward_ids': [(0, 0, {
                'reward_type': 'product',
                'reward_product_id': self.whiteboard_pen.id,
                'reward_product_qty': 1,
                'required_points': 4,
            })],
        })

        partner_aaa = self.env['res.partner'].create({'name': 'Test Partner AAA'})
        partner_bbb = self.env['res.partner'].create({'name': 'Test Partner BBB'})
        partner_ccc = self.env['res.partner'].create({'name': 'Test Partner CCC'})

        self.main_pos_config.write({
            'promo_program_ids': [Command.clear()],
            'module_pos_loyalty': True,
            'loyalty_program_id': loyalty_program.id,
        })

        # Part 1
        self.start_tour(
            "/pos/web?config_id=%d" % self.main_pos_config.id,
            "PosLoyaltyLoyaltyProgram1",
            login="******",
        )

        aaa_loyalty_card = loyalty_program.coupon_ids.filtered(lambda coupon: coupon.partner_id.id == partner_aaa.id)

        self.assertEqual(loyalty_program.pos_order_count, 1)
        self.assertAlmostEqual(aaa_loyalty_card.points, 4)

        # Part 2
        self.start_tour(
            "/pos/web?config_id=%d" % self.main_pos_config.id,
            "PosLoyaltyLoyaltyProgram2",
            login="******",
        )

        self.assertEqual(loyalty_program.pos_order_count, 2, msg='Only 2 orders should have reward lines.')
        self.assertAlmostEqual(aaa_loyalty_card.points, 1)

        bbb_loyalty_card = loyalty_program.coupon_ids.filtered(lambda coupon: coupon.partner_id.id == partner_bbb.id)
        ccc_loyalty_card = loyalty_program.coupon_ids.filtered(lambda coupon: coupon.partner_id.id == partner_ccc.id)

        self.assertAlmostEqual(bbb_loyalty_card.points, 3, msg='Reference: Order3_BBB')
        self.assertAlmostEqual(ccc_loyalty_card.points, 4, msg='Reference: Order2_CCC')

        reward_orderline = self.main_pos_config.current_session_id.order_ids[-1].lines.filtered(lambda line: line.is_reward_line)
        self.assertEqual(len(reward_orderline.ids), 0, msg='Reference: Order4_no_reward. Last order should have no reward line.')
Ejemplo n.º 21
0
    def test_mail_mail_attachment_access(self):
        mail = self.env['mail.mail'].create({
            'body_html':
            'Test',
            'email_to':
            '*****@*****.**',
            'partner_ids': [(4, self.user_employee.partner_id.id)],
            'attachment_ids': [
                (0, 0, {
                    'name': 'file 1',
                    'datas': 'c2VjcmV0'
                }),
                (0, 0, {
                    'name': 'file 2',
                    'datas': 'c2VjcmV0'
                }),
                (0, 0, {
                    'name': 'file 3',
                    'datas': 'c2VjcmV0'
                }),
                (0, 0, {
                    'name': 'file 4',
                    'datas': 'c2VjcmV0'
                }),
            ],
        })

        def _patched_check(self, *args, **kwargs):
            if self.env.is_superuser():
                return
            if any(attachment.name in ('file 2', 'file 4')
                   for attachment in self):
                raise AccessError('No access')

        mail.invalidate_recordset()

        new_attachment = self.env['ir.attachment'].create({
            'name': 'new file',
            'datas': 'c2VjcmV0',
        })

        with patch.object(type(self.env['ir.attachment']), 'check',
                          _patched_check):
            # Sanity check
            self.assertEqual(mail.restricted_attachment_count, 2)
            self.assertEqual(len(mail.unrestricted_attachment_ids), 2)
            self.assertEqual(mail.unrestricted_attachment_ids.mapped('name'),
                             ['file 1', 'file 3'])

            # Add a new attachment
            mail.write({
                'unrestricted_attachment_ids':
                [Command.link(new_attachment.id)],
            })
            self.assertEqual(mail.restricted_attachment_count, 2)
            self.assertEqual(len(mail.unrestricted_attachment_ids), 3)
            self.assertEqual(mail.unrestricted_attachment_ids.mapped('name'),
                             ['file 1', 'file 3', 'new file'])
            self.assertEqual(len(mail.attachment_ids), 5)

            # Remove an attachment
            mail.write({
                'unrestricted_attachment_ids':
                [Command.unlink(new_attachment.id)],
            })
            self.assertEqual(mail.restricted_attachment_count, 2)
            self.assertEqual(len(mail.unrestricted_attachment_ids), 2)
            self.assertEqual(mail.unrestricted_attachment_ids.mapped('name'),
                             ['file 1', 'file 3'])
            self.assertEqual(len(mail.attachment_ids), 4)

            # Reset command
            mail.invalidate_recordset()
            mail.write({'unrestricted_attachment_ids': [Command.clear()]})
            self.assertEqual(len(mail.unrestricted_attachment_ids), 0)
            self.assertEqual(len(mail.attachment_ids), 2)

            # Read in SUDO
            mail.invalidate_recordset()
            self.assertEqual(mail.sudo().restricted_attachment_count, 2)
            self.assertEqual(len(mail.sudo().unrestricted_attachment_ids), 0)
Ejemplo n.º 22
0
    def test_onchange_one2many_multi(self):
        """ test the effect of multiple onchange methods on one2many fields """
        partner1 = self.env['res.partner'].create({'name': 'A partner'})
        multi = self.env['test_new_api.multi'].create({'partner': partner1.id})
        line1 = multi.lines.create({'multi': multi.id})

        field_onchange = multi._onchange_spec()
        self.assertEqual(
            field_onchange, {
                'name': '1',
                'partner': '1',
                'lines': None,
                'lines.name': None,
                'lines.partner': None,
                'lines.tags': None,
                'lines.tags.name': None,
            })

        values = multi._convert_to_write(
            {key: multi[key]
             for key in ('name', 'partner', 'lines')})
        self.assertEqual(
            values, {
                'name': partner1.name,
                'partner': partner1.id,
                'lines': [Command.set([line1.id])],
            })

        # modify 'partner'
        #   -> set 'partner' on all lines
        #   -> recompute 'name'
        #       -> set 'name' on all lines
        partner2 = self.env['res.partner'].create({'name': 'A second partner'})
        values = {
            'name':
            partner1.name,
            'partner':
            partner2.id,  # this one just changed
            'lines': [
                Command.set([line1.id]),
                Command.create({
                    'name': False,
                    'partner': False,
                    'tags': [Command.clear()]
                })
            ],
        }
        self.env.cache.invalidate()

        result = multi.onchange(values, 'partner', field_onchange)
        self.assertEqual(
            result['value'], {
                'name':
                partner2.name,
                'lines': [
                    Command.clear(),
                    Command.update(
                        line1.id, {
                            'name': partner2.name,
                            'partner': (partner2.id, partner2.name),
                            'tags': [Command.clear()],
                        }),
                    Command.create({
                        'name': partner2.name,
                        'partner': (partner2.id, partner2.name),
                        'tags': [Command.clear()],
                    }),
                ],
            })

        # do it again, but this time with a new tag on the second line
        values = {
            'name':
            partner1.name,
            'partner':
            partner2.id,  # this one just changed
            'lines': [
                Command.set([line1.id]),
                Command.create({
                    'name':
                    False,
                    'partner':
                    False,
                    'tags': [Command.clear(),
                             Command.create({'name': 'Tag'})]
                })
            ],
        }
        self.env.cache.invalidate()
        result = multi.onchange(values, 'partner', field_onchange)
        expected_value = {
            'name':
            partner2.name,
            'lines': [
                Command.clear(),
                Command.update(
                    line1.id, {
                        'name': partner2.name,
                        'partner': (partner2.id, partner2.name),
                        'tags': [Command.clear()],
                    }),
                Command.create({
                    'name':
                    partner2.name,
                    'partner': (partner2.id, partner2.name),
                    'tags': [Command.clear(),
                             Command.create({'name': 'Tag'})],
                }),
            ],
        }
        self.assertEqual(result['value'], expected_value)

        # ensure ID is not returned when asked and a many2many record is set to be created
        self.env.cache.invalidate()

        result = multi.onchange(
            values, 'partner', dict(field_onchange, **{'lines.tags.id': None}))
        self.assertEqual(result['value'], expected_value)

        # ensure inverse of one2many field is not returned
        self.env.cache.invalidate()

        result = multi.onchange(values, 'partner',
                                dict(field_onchange, **{'lines.multi': None}))
        self.assertEqual(result['value'], expected_value)
Ejemplo n.º 23
0
    def test_onchange_one2many(self):
        """ test the effect of onchange() on one2many fields """
        USER = self.env.user

        # create an independent message
        message1 = self.Message.create({'body': "ABC"})
        message2 = self.Message.create({'body': "ABC"})
        self.assertEqual(message1.name, "[%s] %s" % ('', USER.name))

        field_onchange = self.Discussion._onchange_spec()
        self.assertEqual(field_onchange.get('name'), '1')
        self.assertEqual(field_onchange.get('messages'), '1')
        self.assertItemsEqual(
            strip_prefix('messages.', field_onchange),
            ['author', 'body', 'name', 'size', 'important'],
        )

        # modify discussion name
        values = {
            'name':
            "Foo",
            'categories': [],
            'moderator':
            False,
            'participants': [],
            'messages': [
                Command.link(message1.id),
                Command.link(message2.id),
                Command.update(message2.id, {'body': "XYZ"}),
                Command.create({
                    'name': "[%s] %s" % ('', USER.name),
                    'body': "ABC",
                    'author': USER.id,
                    'size': 3,
                    'important': False,
                }),
            ],
        }
        self.env.cache.invalidate()
        result = self.Discussion.onchange(values, 'name', field_onchange)
        self.assertIn('messages', result['value'])
        self.assertEqual(
            result['value']['messages'],
            [
                Command.clear(),
                Command.update(
                    message1.id, {
                        'name': "[%s] %s" % ("Foo", USER.name),
                        'body': "ABC",
                        'author': USER.name_get()[0],
                        'size': 3,
                        'important': False,
                    }),
                Command.update(
                    message2.id,
                    {
                        'name': "[%s] %s" % ("Foo", USER.name),
                        'body': "XYZ",  # this must be sent back
                        'author': USER.name_get()[0],
                        'size': 3,
                        'important': False,
                    }),
                Command.create({
                    'name': "[%s] %s" % ("Foo", USER.name),
                    'body': "ABC",
                    'author': USER.name_get()[0],
                    'size': 3,
                    'important': False,
                }),
            ])

        # ensure onchange changing one2many without subfield works
        one_level_fields = {
            k: v
            for k, v in field_onchange.items() if k.count('.') < 1
        }
        values = dict(values, name='{generate_dummy_message}')
        result = self.Discussion.with_context(
            generate_dummy_message=True).onchange(values, 'name',
                                                  one_level_fields)
        self.assertEqual(result['value']['messages'], [
            Command.clear(),
            Command.link(message1.id),
            Command.link(message2.id),
            Command.create({}),
            Command.create({}),
        ])
Ejemplo n.º 24
0
 def action_return_to_list(self):
     self.production_detailed_vals_ids = [Command.clear()]
     self.counter = 0
     action = self.env['ir.actions.actions']._for_xml_id('mrp.action_mrp_production_split_multi')
     action['res_id'] = self.production_split_multi_id.id
     return action
Ejemplo n.º 25
0
    def _compute_available_payment_method_ids(self):
        """
        Compute the available payment methods id by respecting the following rules:
            Methods of mode 'unique' cannot be used twice on the same company
            Methods of mode 'multi' cannot be used twice on the same journal
        """
        method_information = self.env['account.payment.method']._get_payment_method_information()
        pay_methods = self.env['account.payment.method'].search([('code', 'in', list(method_information.keys()))])
        pay_method_by_code = {x.code + x.payment_type: x for x in pay_methods}
        unique_pay_methods = [k for k, v in method_information.items() if v['mode'] == 'unique']

        pay_methods_by_company = {}
        pay_methods_by_journal = {}
        if unique_pay_methods:
            self._cr.execute('''
                SELECT
                    journal.id,
                    journal.company_id,
                    ARRAY_AGG(DISTINCT apm.id)
                FROM account_payment_method_line apml
                JOIN account_journal journal ON journal.id = apml.journal_id
                JOIN account_payment_method apm ON apm.id = apml.payment_method_id
                WHERE apm.code IN %s
                GROUP BY
                    journal.id,
                    journal.company_id
            ''', [tuple(unique_pay_methods)])
            for journal_id, company_id, payment_method_ids in self._cr.fetchall():
                pay_methods_by_company[company_id] = set(payment_method_ids)
                pay_methods_by_journal[journal_id] = set(payment_method_ids)

        pay_method_ids_commands_x_journal = {j: [Command.clear()] for j in self}
        for payment_type in ('inbound', 'outbound'):
            for code, vals in method_information.items():
                payment_method = pay_method_by_code.get(code + payment_type)

                if not payment_method:
                    continue

                # Get the domain of the journals on which the current method is usable.
                method_domain = payment_method._get_payment_method_domain()

                for journal in self.filtered_domain(method_domain):
                    protected_pay_method_ids = pay_methods_by_company.get(journal.company_id._origin.id, set()) \
                                               - pay_methods_by_journal.get(journal._origin.id, set())

                    if payment_type == 'inbound':
                        lines = journal.inbound_payment_method_line_ids
                    else:
                        lines = journal.outbound_payment_method_line_ids

                    already_used = payment_method in lines.payment_method_id
                    is_protected = payment_method.id in protected_pay_method_ids
                    if vals['mode'] == 'unique' and (already_used or is_protected):
                        continue

                    # Only the manual payment method can be used multiple time on a single journal.
                    if payment_method.code != "manual" and already_used:
                        continue

                    pay_method_ids_commands_x_journal[journal].append(Command.link(payment_method.id))

        for journal, pay_method_ids_commands in pay_method_ids_commands_x_journal.items():
            journal.available_payment_method_ids = pay_method_ids_commands