def _compute_line_ids(self): for record in self: if not record.foo: continue if any(line.foo == record.foo for line in record.line_ids): continue # add a line with the same value as 'foo' record.line_ids = [Command.create({'foo': record.foo})]
def _compute_user_ids(self): for portal_wizard in self: portal_wizard.user_ids = [ Command.create({ 'partner_id': partner.id, 'email': partner.email, }) for partner in portal_wizard.partner_ids ]
def _get_demo_data_reconcile_model(self): cid = self.env.company.id return ('account.reconcile.model', { f'{cid}_reconcile_from_label': { 'name': 'Line with Bank Fees', 'rule_type': 'writeoff_suggestion', 'match_label': 'contains', 'match_label_param': 'BRT', 'decimal_separator': ',', 'line_ids': [ Command.create({ 'label': 'Due amount', 'account_id': self._get_demo_account( 'income', 'account.data_account_type_revenue', self.env.company, ).id, 'amount_type': 'regex', 'amount_string': r'BRT: ([\d,]+)', }), Command.create({ 'label': 'Bank Fees', 'account_id': self._get_demo_account( 'cost_of_goods_sold', 'account.data_account_type_direct_costs', self.env.company, ).id, 'amount_type': 'percentage', 'amount_string': '100', }), ] }, })
def test_portal_user_cannot_see_all_assignees(self): """ Test when the portal sees a task he cannot see all the assignees. Because of a ir.rule in res.partner filters the assignees, the portal can only see the assignees in the same company than him. Test Cases: ========== 1) add many assignees in a task 2) check the portal user can read no assignee in this task. Should have an AccessError exception """ self.task_cow.write( {'user_ids': [Command.link(self.user_projectmanager.id)]}) with self.assertRaises( AccessError, msg= "Should not accept the portal user to access to a task he does not follow it and its project." ): self.task_cow.with_user(self.user_portal).read( ['portal_user_names']) self.assertEqual(len(self.task_cow.user_ids), 2, '2 users should be assigned in this task.') project_share_wizard = self.env['project.share.wizard'].create({ 'access_mode': 'edit', 'res_model': 'project.project', 'res_id': self.project_cows.id, 'partner_ids': [ Command.link(self.user_portal.partner_id.id), ], }) project_share_wizard.action_send_mail() self.assertFalse( self.task_cow.with_user(self.user_portal).user_ids, 'the portal user should see no assigness in the task.') task_portal_read = self.task_cow.with_user(self.user_portal).read( ['portal_user_names']) self.assertEqual( self.task_cow.portal_user_names, task_portal_read[0]['portal_user_names'], 'the portal user should see assignees name in the task via the `portal_user_names` field.' )
def _timesheet_preprocess(self, vals): """ Deduce other field values from the one given. Overrride this to compute on the fly some field that can not be computed fields. :param values: dict values for `create`or `write`. """ # task implies analytic account and tags if vals.get('task_id') and not vals.get('account_id'): task = self.env['project.task'].browse(vals.get('task_id')) task_analytic_account_id = task._get_task_analytic_account_id() vals['account_id'] = task_analytic_account_id.id vals['company_id'] = task_analytic_account_id.company_id.id or task.company_id.id if vals.get('tag_ids'): vals['tag_ids'] += [Command.link(tag_id.id) for tag_id in task.analytic_tag_ids] else: vals['tag_ids'] = [Command.set(task.analytic_tag_ids.ids)] if not task_analytic_account_id.active: raise UserError(_('You cannot add timesheets to a project or a task linked to an inactive analytic account.')) # project implies analytic account if vals.get('project_id') and not vals.get('account_id'): project = self.env['project.project'].browse(vals.get('project_id')) vals['account_id'] = project.analytic_account_id.id vals['company_id'] = project.analytic_account_id.company_id.id or project.company_id.id if vals.get('tag_ids'): vals['tag_ids'] += [Command.link(tag_id.id) for tag_id in project.analytic_tag_ids] else: vals['tag_ids'] = [Command.set(project.analytic_tag_ids.ids)] if not project.analytic_account_id.active: raise UserError(_('You cannot add timesheets to a project linked to an inactive analytic account.')) # employee implies user if vals.get('employee_id') and not vals.get('user_id'): employee = self.env['hr.employee'].browse(vals['employee_id']) vals['user_id'] = employee.user_id.id # force customer partner, from the task or the project if (vals.get('project_id') or vals.get('task_id')) and not vals.get('partner_id'): partner_id = False if vals.get('task_id'): partner_id = self.env['project.task'].browse(vals['task_id']).partner_id.id else: partner_id = self.env['project.project'].browse(vals['project_id']).partner_id.id if partner_id: vals['partner_id'] = partner_id # set timesheet UoM from the AA company (AA implies uom) if 'product_uom_id' not in vals and all(v in vals for v in ['account_id', 'project_id']): # project_id required to check this is timesheet flow analytic_account = self.env['account.analytic.account'].sudo().browse(vals['account_id']) vals['product_uom_id'] = analytic_account.company_id.project_time_mode_id.id return vals
def test_warn_company_no_company_field(self): """ If one of the failing rules mentions company_id, add a note that this might be a multi-company issue, but the record doesn't have company_id field then no information about the company is showed. """ self.env.ref('base.group_no_one').write( {'users': [Command.link(self.user.id)]}) self.env.ref('base.group_user').write( {'users': [Command.link(self.user.id)]}) ChildModel = self.env['test_access_right.child'].sudo() self.env['ir.rule'].create({ 'name': 'rule 0', 'model_id': self.env['ir.model'].search([('model', '=', ChildModel._name)]).id, 'groups': [], 'domain_force': '[("parent_id.company_id", "=", user.company_id.id)]', 'perm_read': True, }) self.record.sudo().company_id = self.env['res.company'].create( {'name': 'Brosse Inc.'}) self.user.sudo().company_ids = [ Command.link(self.record.company_id.id) ] child_record = ChildModel.create({ 'parent_id': self.record.id }).with_user(self.user) with self.assertRaises(AccessError) as ctx: _ = child_record.parent_id self.assertEqual( ctx.exception.args[0], """Due to security restrictions, you are not allowed to access 'Object for testing company ir rule' (test_access_right.child) records. Records: %s (id=%s) User: %s (id=%s) This restriction is due to the following rules: - rule 0 Note: this might be a multi-company issue. Contact your administrator to request access if necessary.""" % (child_record.display_name, child_record.id, self.user.name, self.user.id))
def _create_liquidity_journal_suspense_account(self, company, code_digits): account = super()._create_liquidity_journal_suspense_account( company, code_digits) if company.account_fiscal_country_id.code == 'NL': account.tag_ids = [ Command.link(self.env.ref('l10n_nl.account_tag_25').id) ] return account
def test_project_sharing_access(self): """ Check if the different user types can access to project sharing feature as expected. """ with self.assertRaises(AccessError, msg='The public user should not have any access to project sharing feature of the portal project.'): self.project_portal.with_user(self.user_public)._check_project_sharing_access() self.assertTrue(self.project_portal.with_user(self.user_projectuser)._check_project_sharing_access(), 'The internal user should have all accesses to project sharing feature of the portal project.') self.assertFalse(self.project_portal.with_user(self.user_portal)._check_project_sharing_access(), 'The portal user should not have any access to project sharing feature of the portal project.') self.project_portal.write({'collaborator_ids': [Command.create({'partner_id': self.user_portal.partner_id.id})]}) self.assertTrue(self.project_portal.with_user(self.user_portal)._check_project_sharing_access(), 'The portal user can access to project sharing feature of the portal project.')
def test_export_import(self): """ Ensure export+import gives the same result as loading a language """ # load language and generate missing terms to create missing empty terms with mute_logger('odoo.addons.base.models.ir_translation'): self.env["base.language.install"].create({ 'lang': 'fr_FR', 'overwrite': True }).lang_install() self.env["base.update.translations"].create({ 'lang': 'fr_FR' }).act_update() translations = self.env["ir.translation"].search([ ('lang', '=', 'fr_FR'), ('module', '=', 'test_translation_import'), ('value', '!=', ''), ]) # minus 3 as the original fr.po contains 3 fake code translations (cf # test_no_duplicate test) which are not found by babel_extract_terms init_translation_count = len(translations) - 3 module = self.env.ref('base.module_test_translation_import') export = self.env["base.language.export"].create({ 'lang': 'fr_FR', 'format': 'po', 'modules': [Command.set([module.id])] }) export.act_getfile() po_file = export.data self.assertIsNotNone(po_file) translations.unlink() import_fr = self.env["base.language.import"].create({ 'name': 'French', 'code': 'fr_FR', 'data': export.data, 'filename': export.name, 'overwrite': False, }) with mute_logger('odoo.addons.base.models.res_lang'): import_fr.import_lang() import_translation = self.env["ir.translation"].search([ ('lang', '=', 'fr_FR'), ('module', '=', 'test_translation_import'), ('value', '!=', ''), ]) self.assertEqual(init_translation_count, len(import_translation))
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")
def test_40_multi(self): # Data: 2 server actions that will be nested action1 = self.action.create({ 'name': 'Subaction1', 'sequence': 1, 'model_id': self.res_partner_model.id, 'state': 'code', 'code': 'action = {"type": "ir.actions.act_window"}', }) action2 = self.action.create({ 'name': 'Subaction2', 'sequence': 2, 'model_id': self.res_partner_model.id, 'crud_model_id': self.res_partner_model.id, 'state': 'object_create', 'fields_lines': [Command.create({'col1': self.res_partner_name_field.id, 'value': 'RaoulettePoiluchette'}), Command.create({'col1': self.res_partner_city_field.id, 'value': 'TestingCity'})], }) action3 = self.action.create({ 'name': 'Subaction3', 'sequence': 3, 'model_id': self.res_partner_model.id, 'state': 'code', 'code': 'action = {"type": "ir.actions.act_url"}', }) self.action.write({ 'state': 'multi', 'child_ids': [Command.set([action1.id, action2.id, action3.id])], }) # Do: run the action res = self.action.with_context(self.context).run() # Test: new partner created # currently res_partner overrides default['name'] whatever its value partner = self.test_partner.search([('name', 'ilike', 'RaoulettePoiluchette')]) self.assertEqual(len(partner), 1) # Test: action returned self.assertEqual(res.get('type'), 'ir.actions.act_url') # Test loops with self.assertRaises(ValidationError): self.action.write({ 'child_ids': [Command.set([self.action.id])] })
def test_60_prefetch_model(self): """ Check the prefetching model. """ partners = self.env['res.partner'].search([('id', 'in', self.partners.ids)], limit=models.PREFETCH_MAX) self.assertTrue(partners) def same_prefetch(a, b): self.assertEqual(set(a._prefetch_ids), set(b._prefetch_ids)) def diff_prefetch(a, b): self.assertNotEqual(set(a._prefetch_ids), set(b._prefetch_ids)) # the recordset operations below use different prefetch sets diff_prefetch(partners, partners.browse()) diff_prefetch(partners, partners[0]) diff_prefetch(partners, partners[:5]) # the recordset operations below share the prefetch set same_prefetch(partners, partners.browse(partners.ids)) same_prefetch(partners, partners.with_user(self.user_demo)) same_prefetch(partners, partners.with_context(active_test=False)) same_prefetch(partners, partners[:10].with_prefetch(partners._prefetch_ids)) # iteration and relational fields should use the same prefetch set self.assertEqual(type(partners).country_id.type, 'many2one') self.assertEqual(type(partners).bank_ids.type, 'one2many') self.assertEqual(type(partners).category_id.type, 'many2many') vals0 = { 'name': 'Empty relational fields', 'country_id': False, 'bank_ids': [], 'category_id': [], } vals1 = { 'name': 'Non-empty relational fields', 'country_id': self.ref('base.be'), 'bank_ids': [Command.create({'acc_number': 'FOO42'})], 'category_id': [Command.link(self.partner_category.id)], } partners = partners.create(vals0) + partners.create(vals1) for partner in partners: same_prefetch(partner, partners) same_prefetch(partner.country_id, partners.country_id) same_prefetch(partner.bank_ids, partners.bank_ids) same_prefetch(partner.category_id, partners.category_id)
def test_res_group_recursion(self): # four groups with no cycle, check them all together a = self.env['res.groups'].create({'name': 'A'}) b = self.env['res.groups'].create({'name': 'B'}) c = self.env['res.groups'].create({ 'name': 'G', 'implied_ids': [Command.set((a + b).ids)] }) d = self.env['res.groups'].create({ 'name': 'D', 'implied_ids': [Command.set(c.ids)] }) self.assertTrue((a + b + c + d)._check_m2m_recursion('implied_ids')) # create a cycle and check a.implied_ids = d self.assertFalse(a._check_m2m_recursion('implied_ids'))
def test_activity_calendar_event_id(self): """Test the computed field "activity_calendar_event_id" which is the event of the next activity. It must evaluate to False if the next activity is not related to an event""" def create_event(name, event_date): return self.env['calendar.event'].create({ 'name': name, 'start': datetime.combine(event_date, time(12, 0, 0)), 'stop': datetime.combine(event_date, time(14, 0, 0)), }) def schedule_meeting_activity(record, date_deadline, calendar_event=False): meeting = record.activity_schedule( 'calendar.calendar_activity_test_default', date_deadline=date_deadline) meeting.calendar_event_id = calendar_event return meeting group_partner_manager = self.env['ir.model.data']._xmlid_to_res_id( 'base.group_partner_manager') self.user_employee.write({ 'tz': self.user_admin.tz, 'groups_id': [Command.link(group_partner_manager)] }) with self.with_user('employee'): test_record = self.env['res.partner'].browse(self.test_record.id) self.assertEqual(test_record.activity_ids, self.env['mail.activity']) now_utc = datetime.now(pytz.UTC) now_user = now_utc.astimezone( pytz.timezone(self.env.user.tz or 'UTC')) today_user = now_user.date() date1 = today_user + relativedelta(days=1) date2 = today_user + relativedelta(days=2) ev1 = create_event('ev1', date1) ev2 = create_event('ev2', date2) act1 = schedule_meeting_activity(test_record, date1) schedule_meeting_activity(test_record, date2, ev2) self.assertFalse( test_record.activity_calendar_event_id, "The next activity does not have a calendar event") act1.calendar_event_id = ev1 self.assertEqual( test_record.activity_calendar_event_id.name, ev1.name, "This should be the calendar event of the next activity")
def _set_count(self): for r in self: r.write({ 'm2m': [ Command.create({'name': str(n)}) for n, v in zip_longest(range(r.count), r.m2m or []) if v is None ] })
def test_create_base_with_lines(self): """ Create records with one2many lines. """ with self.assertQueryCount(__system__=12, demo=12): self.env['test_performance.base'].create({ 'name': 'X', 'line_ids': [Command.create({'value': val}) for val in range(10)], })
def _compute_invalid_addresses(self): for wizard in self: if any(not invoice.partner_id for invoice in wizard.invoice_ids): raise UserError(_('You cannot send an invoice which has no partner assigned.')) invalid_invoices = wizard.invoice_ids.filtered(lambda i: not self.env['snailmail.letter']._is_valid_address(i.partner_id)) wizard.invalid_invoices = len(invalid_invoices) invalid_partner_ids = invalid_invoices.partner_id.ids wizard.invalid_addresses = len(invalid_partner_ids) wizard.invalid_partner_ids = [Command.set(invalid_partner_ids)]
def _merge(self, partner_ids, dst_partner=None, extra_checks=True): """ private implementation of merge partner :param partner_ids : ids of partner to merge :param dst_partner : record of destination res.partner :param extra_checks: pass False to bypass extra sanity check (e.g. email address) """ # super-admin can be used to bypass extra checks if self.env.is_admin(): extra_checks = False Partner = self.env['res.partner'] partner_ids = Partner.browse(partner_ids).exists() if len(partner_ids) < 2: return if len(partner_ids) > 3: raise UserError(_("For safety reasons, you cannot merge more than 3 contacts together. You can re-open the wizard several times if needed.")) # check if the list of partners to merge contains child/parent relation child_ids = self.env['res.partner'] for partner_id in partner_ids: child_ids |= Partner.search([('id', 'child_of', [partner_id.id])]) - partner_id if partner_ids & child_ids: raise UserError(_("You cannot merge a contact with one of his parent.")) if extra_checks and len(set(partner.email for partner in partner_ids)) > 1: raise UserError(_("All contacts must have the same email. Only the Administrator can merge contacts with different emails.")) # remove dst_partner from partners to merge if dst_partner and dst_partner in partner_ids: src_partners = partner_ids - dst_partner else: ordered_partners = self._get_ordered_partner(partner_ids.ids) dst_partner = ordered_partners[-1] src_partners = ordered_partners[:-1] _logger.info("dst_partner: %s", dst_partner.id) # FIXME: is it still required to make and exception for account.move.line since accounting v9.0 ? if extra_checks and 'account.move.line' in self.env and self.env['account.move.line'].sudo().search([('partner_id', 'in', [partner.id for partner in src_partners])]): raise UserError(_("Only the destination contact may be linked to existing Journal Items. Please ask the Administrator if you need to merge several contacts linked to existing Journal Items.")) # Make the company of all related users consistent with destination partner company if dst_partner.company_id: partner_ids.mapped('user_ids').sudo().write({ 'company_ids': [Command.link(dst_partner.company_id.id)], 'company_id': dst_partner.company_id.id }) # call sub methods to do the merge self._update_foreign_keys(src_partners, dst_partner) self._update_reference_fields(src_partners, dst_partner) self._update_values(src_partners, dst_partner) self._log_merge_operation(src_partners, dst_partner) # delete source partner, since they are merged src_partners.unlink()
def test_broken_configuration(self): percent_tax = self.env['account.tax'].create({ 'name': "percent_tax", 'amount_type': 'percent', 'amount': 10.0, }) invoice = self.env['account.move'].create({ 'move_type': 'out_invoice', 'partner_id': self.partner_a.id, 'invoice_date': '2019-01-01', 'invoice_line_ids': [ Command.create({ 'name': 'line1', 'account_id': self.company_data['default_account_revenue'].id, 'price_unit': 1000.0, 'tax_ids': [Command.set(percent_tax.ids)], }), ] }) base_lines, tax_lines = self._dispatch_move_lines(invoice) # Break the configuration tax_lines.account_id = self.company_data['default_account_assets'] tax_details = self._get_tax_details(fallback=True) self.assertTaxDetailsValues( tax_details, [ { 'base_line_id': base_lines[0].id, 'tax_line_id': tax_lines[0].id, 'base_amount': -1000.0, 'tax_amount': -100.0, }, ], ) self.assertTotalAmounts(invoice, tax_details)
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, })], )
def unstar_all(self): """ Unstar messages for the current partner. """ partner_id = self.env.user.partner_id.id starred_messages = self.search([('starred_partner_ids', 'in', partner_id)]) starred_messages.write({'starred_partner_ids': [Command.unlink(partner_id)]}) ids = [m.id for m in starred_messages] notification = {'type': 'toggle_star', 'message_ids': ids, 'starred': False} self.env['bus.bus'].sendone((self._cr.dbname, 'res.partner', self.env.user.partner_id.id), notification)
def test_write_4_one2many(self): """ Check that we can write on an inherited one2many field. """ box = self.env.ref('test_inherits.box_a') box.write({'line_ids': [Command.create({'name': 'Line 1'})]}) self.assertTrue(all(box.line_ids._ids)) self.assertEqual(box.line_ids.mapped('name'), ['Line 1']) self.assertEqual(box.line_ids, box.unit_id.line_ids) box.flush() box.invalidate_cache(['line_ids']) box.write({'line_ids': [Command.create({'name': 'Line 2'})]}) self.assertTrue(all(box.line_ids._ids)) self.assertEqual(box.line_ids.mapped('name'), ['Line 1', 'Line 2']) self.assertEqual(box.line_ids, box.unit_id.line_ids) box.flush() box.invalidate_cache(['line_ids']) box.write({'line_ids': [Command.update(box.line_ids[0].id, {'name': 'First line'})]}) self.assertTrue(all(box.line_ids._ids)) self.assertEqual(box.line_ids.mapped('name'), ['First line', 'Line 2']) self.assertEqual(box.line_ids, box.unit_id.line_ids)
def test_amounts_sign(self): for tax_sign in (1, -1): tax = self.env['account.tax'].create({ 'name': "tax", 'amount_type': 'percent', 'amount': tax_sign * 10.0, }) amounts_list = [ (-1000.0, 7000.0, -2000.0), (1000.0, -7000.0, 2000.0), (-1000.0, -7000.0, 2000.0), (1000.0, 7000.0, -2000.0), ] for amounts in amounts_list: with self.subTest(tax_sign=tax_sign, amounts=amounts): invoice = self.env['account.move'].create({ 'move_type': 'in_invoice', 'partner_id': self.partner_a.id, 'invoice_date': '2019-01-01', 'invoice_line_ids': [ Command.create({ 'name': 'line2', 'account_id': self.company_data['default_account_revenue'].id, 'price_unit': amount, 'tax_ids': [Command.set(tax.ids)], }) for amount in amounts], }) _base_lines, tax_lines = self._dispatch_move_lines(invoice) tax_details = self._get_tax_details(extra_domain=[('move_id', '=', invoice.id)]) self.assertTaxDetailsValues( tax_details, [ { 'tax_line_id': tax_lines[0].id, 'base_amount': amount, 'tax_amount': tax_sign * amount * 0.1, } for amount in amounts], ) self.assertTotalAmounts(invoice, tax_details)
def restart_google_synchronization(self): self.ensure_one() if not self.google_cal_account_id: self.google_cal_account_id = self.env[ 'google.calendar.credentials'].sudo().create([{ 'user_ids': [Command.set(self.ids)] }]) self.google_synchronization_stopped = False self.env['calendar.recurrence']._restart_google_sync() self.env['calendar.event']._restart_google_sync()
def setUpClass(cls): super(TestMailGroupModeration, cls).setUpClass() cls.test_group_2 = cls.env['mail.group'].create({ 'access_mode': 'members', 'alias_name': 'test.mail.group.2', 'moderation': True, 'moderator_ids': [Command.link(cls.user_employee.id)], 'name': 'Test group 2', })
def _get_livechat_mail_channel_vals(self, anonymous_name, operator, user_id=None, country_id=None): # partner to add to the mail.channel operator_partner_id = operator.partner_id.id channel_partner_to_add = [ Command.create({ 'partner_id': operator_partner_id, 'is_pinned': False }) ] visitor_user = False if user_id: visitor_user = self.env['res.users'].browse(user_id) if visitor_user and visitor_user.active and visitor_user != operator: # valid session user (not public) channel_partner_to_add.append( Command.create({'partner_id': visitor_user.partner_id.id})) return { 'channel_last_seen_partner_ids': channel_partner_to_add, 'livechat_active': True, 'livechat_operator_id': operator_partner_id, 'livechat_channel_id': self.id, 'anonymous_name': False if user_id else anonymous_name, 'country_id': country_id, 'channel_type': 'livechat', 'name': ' '.join([ visitor_user.display_name if visitor_user else anonymous_name, operator.livechat_username if operator.livechat_username else operator.name ]), 'public': 'private', }
def test_frozendict_hash(self): """ Ensure that a frozendict is hashable. """ # dict with simple values hash(frozendict({'name': 'Joe', 'age': 42})) # dict with tuples, lists, and embedded dicts hash(frozendict({ 'user_id': (42, 'Joe'), 'line_ids': [Command.create({'values': [42]})], }))
def _get_backorder_move_vals(self): self.ensure_one() return { 'state': 'confirmed', 'reservation_date': self.reservation_date, 'date_deadline': self.date_deadline, 'manual_consumption': self.bom_line_id.manual_consumption or self.product_id.tracking != 'none', 'move_orig_ids': [Command.link(m.id) for m in self.mapped('move_orig_ids')], 'move_dest_ids': [Command.link(m.id) for m in self.mapped('move_dest_ids')], 'procure_method': self.procure_method, }
def test_read(self): """ because of prefetching, read() goes through a different codepath to apply rules """ self.env.ref('base.group_no_one').write( {'users': [Command.link(self.user.id)]}) self.env.ref('base.group_user').write( {'users': [Command.link(self.user.id)]}) self._make_rule('rule 0', "[('company_id', '=', user.company_id.id)]", attr='read') self._make_rule('rule 1', '[("val", "=", 1)]', global_=True, attr='read') with self.assertRaises(AccessError) as ctx: _ = self.record.val self.assertEqual( ctx.exception.args[0], """Due to security restrictions, you are not allowed to access 'Object For Test Access Right' (test_access_right.some_obj) records. Records: %s (id=%s) User: %s (id=%s) This restriction is due to the following rules: - rule 0 - rule 1 Note: this might be a multi-company issue. Contact your administrator to request access if necessary.""" % (self.record.display_name, self.record.id, self.user.name, self.user.id)) p = self.env['test_access_right.parent'].create( {'obj_id': self.record.id}) p.flush() p.invalidate_cache() with self.assertRaisesRegex( AccessError, r"Implicitly accessed through 'Object for testing related access rights' \(test_access_right.parent\)\.", ): p.with_user(self.user).val
def setUpClass(cls): super().setUpClass() # use a single value for today throughout the tests to avoid weird scenarios around midnight cls.today = date.today() baseUser = cls.env['res.users'].create({ 'email': '*****@*****.**', 'groups_id': [Command.link(cls.env.ref('base.group_user').id)], 'login': '******', 'name': 'Ernest Employee', 'notification_type': 'inbox', 'signature': '--\nErnest', }) cls.partner = baseUser.partner_id cls.users = baseUser + cls.env['res.users'].create( { 'name': 'test1', 'login': '******', 'email': '*****@*****.**', 'partner_id': cls.partner.id, }) cls.employees = cls.env['hr.employee'].create([{ 'user_id': user.id, } for user in cls.users]) cls.leave_type = cls.env['hr.leave.type'].create({ 'requires_allocation': 'no', 'name': 'Legal Leaves', 'time_type': 'leave', }) cls.leaves = cls.env['hr.leave'].create([{ 'date_from': cls.today + relativedelta(days=-2), 'date_to': cls.today + relativedelta(days=2), 'employee_id': cls.employees[0].id, 'holiday_status_id': cls.leave_type.id, }, { 'date_from': cls.today + relativedelta(days=-2), 'date_to': cls.today + relativedelta(days=3), 'employee_id': cls.employees[1].id, 'holiday_status_id': cls.leave_type.id, }])