Exemple #1
0
 def test_subtask_log_timesheet(self):
     """ Test parent task takes into account the timesheets of its sub-tasks.
         Test Case:
         ----------
         1) Create parent task
         2) Create child/subtask task
         3) Enter the 8 hour timesheet in the child task
         4) Check subtask Effective hours in parent task
     """
     self.task1.child_ids = [Command.set([self.task2.id])]
     self.env['account.analytic.line'].create({
         'name':
         'FirstTimeSheet',
         'project_id':
         self.project_customer.id,
         'task_id':
         self.task2.id,
         'unit_amount':
         8.0,
         'employee_id':
         self.empl_employee2.id,
     })
     self.assertEqual(
         self.task1.subtask_effective_hours, 8,
         'Hours Spent on Sub-tasks should be 8 hours in Parent Task')
     self.task1.child_ids = [Command.clear()]
Exemple #2
0
    def setUpClass(cls, chart_template_ref=None):
        super().setUpClass(chart_template_ref=chart_template_ref)

        cls.company_a = cls.company_data['company']
        cls.company_b = cls.company_data_2['company']

        cls.user_company_a = cls.internal_user
        cls.user_company_b = cls.env['res.users'].create({
            'name': f"{cls.company_b.name} User (TEST)",
            'login': '******',
            'password': '******',
            'company_id': cls.company_b.id,
            'company_ids': [Command.set(cls.company_b.ids)],
            'groups_id': [Command.link(cls.group_user.id)],
        })
        cls.user_multi_company = cls.env['res.users'].create({
            'name': "Multi Company User (TEST)",
            'login': '******',
            'password': '******',
            'company_id': cls.company_a.id,
            'company_ids': [Command.set([cls.company_a.id, cls.company_b.id])],
            'groups_id': [Command.link(cls.group_user.id)],
        })

        cls.acquirer_company_b = cls._prepare_acquirer(company=cls.company_b)
Exemple #3
0
    def setUpClass(cls):
        super().setUpClass()

        cls.company_a = cls.env.company
        cls.company_b = cls.env['res.company'].create(
            {'name': "Odoo Inc (TEST)"})

        cls.user_company_a = cls.internal_user
        cls.user_company_b = cls.env['res.users'].create({
            'name':
            f"{cls.company_b.name} User (TEST)",
            'login':
            '******',
            'password':
            '******',
            'company_id':
            cls.company_b.id,
            'company_ids': [Command.set(cls.company_b.ids)],
            'groups_id': [Command.link(cls.group_user.id)],
        })
        cls.user_multi_company = cls.env['res.users'].create({
            'name':
            "Multi Company User (TEST)",
            'login':
            '******',
            'password':
            '******',
            'company_id':
            cls.company_a.id,
            'company_ids': [Command.set([cls.company_a.id, cls.company_b.id])],
            'groups_id': [Command.link(cls.group_user.id)],
        })

        cls.acquirer_company_b = cls._prepare_acquirer(company=cls.company_b)
 def setUpClass(cls):
     super().setUpClass()
     cls.users = cls.env['test_read_group.user'].create([
         {
             'name': 'Mario'
         },
         {
             'name': 'Luigi'
         },
     ])
     cls.tasks = cls.env['test_read_group.task'].create([
         {   # both users
             'name': "Super Mario Bros.",
             'user_ids': [Command.set(cls.users.ids)],
         },
         {   # mario only
             'name': "Paper Mario",
             'user_ids': [Command.set(cls.users[0].ids)],
         },
         {   # luigi only
             'name': "Luigi's Mansion",
             'user_ids': [Command.set(cls.users[1].ids)],
         },
         {   # no user
             'name': 'Donkey Kong',
             'user_ids': [Command.set([])],
         },
     ])
Exemple #5
0
    def test_cyclic_dependencies(self):
        """ Test the cyclic dependencies

            Test Case:
            =========
            1) Check initial setting on three tasks
            2) Add task2 as dependency in task1
            3) Add task3 as dependency in task2
            4) Add task1 as dependency in task3 and check a validation error is raised
            5) Add task1 as dependency in task2 and check a validation error is raised
        """
        # 1) Check initial setting on three tasks
        self.assertTrue(
            len(self.task_1.depend_on_ids) == len(self.task_2.depend_on_ids) ==
            len(self.task_3.depend_on_ids) == 0,
            "The three tasks should depend on no tasks.")
        self.assertTrue(self.task_1.allow_task_dependencies,
                        'The task dependencies feature should be enable.')
        self.assertTrue(self.task_2.allow_task_dependencies,
                        'The task dependencies feature should be enable.')
        self.assertTrue(self.task_3.allow_task_dependencies,
                        'The task dependencies feature should be enable.')

        # 2) Add task2 as dependency in task1
        self.task_1.write({
            'depend_on_ids': [Command.link(self.task_2.id)],
        })
        self.assertEqual(len(self.task_1.depend_on_ids), 1,
                         'The task 1 should have one dependency.')

        # 3) Add task3 as dependency in task2
        self.task_2.write({
            'depend_on_ids': [Command.link(self.task_3.id)],
        })
        self.assertEqual(len(self.task_2.depend_on_ids), 1,
                         "The task 2 should have one dependency.")

        # 4) Add task1 as dependency in task3 and check a validation error is raised
        with self.assertRaises(ValidationError), self.cr.savepoint():
            self.task_3.write({
                'depend_on_ids': [Command.link(self.task_1.id)],
            })
        self.assertEqual(
            len(self.task_3.depend_on_ids), 0,
            "The dependency should not be added in the task 3 because of a cyclic dependency."
        )

        # 5) Add task1 as dependency in task2 and check a validation error is raised
        with self.assertRaises(ValidationError), self.cr.savepoint():
            self.task_2.write({
                'depend_on_ids': [Command.link(self.task_1.id)],
            })
        self.assertEqual(
            len(self.task_2.depend_on_ids), 1,
            "The number of dependencies should no change in the task 2 because of a cyclic dependency."
        )
Exemple #6
0
    def test_computes_auto_fill(self):
        free_product = self.env['product.product'].create({
            'name': 'Free product',
            'list_price': 0.0,
        })
        dummy_product = self.env['product.product'].create({
            'name': 'Dummy product',
            'list_price': 0.0,
        })
        # Test pre-computes of lines with order
        order = self.env['sale.order'].create({
            'partner_id': self.partner_a.id,
            'order_line': [
                Command.create({
                    'display_type': 'line_section',
                    'name': 'Dummy section',
                }),
                Command.create({
                    'display_type': 'line_section',
                    'name': 'Dummy section',
                }),
                Command.create({
                    'product_id': free_product.id,
                }),
                Command.create({
                    'product_id': dummy_product.id,
                })
            ]
        })

        # Test pre-computes of lines creation alone
        # Ensures the creation works fine even if the computes
        # are triggered after the defaults
        order = self.env['sale.order'].create({
            'partner_id': self.partner_a.id,
        })
        self.env['sale.order.line'].create([
            {
                'display_type': 'line_section',
                'name': 'Dummy section',
                'order_id': order.id,
            }, {
                'display_type': 'line_section',
                'name': 'Dummy section',
                'order_id': order.id,
            }, {
                'product_id': free_product.id,
                'order_id': order.id,
            }, {
                'product_id': dummy_product.id,
                'order_id': order.id,
            }
        ])
Exemple #7
0
 def _onchange_authorize_payment_method_type(self):
     if self.authorize_payment_method_type == 'bank_account':
         self.display_as = _("Bank (powered by Authorize)")
         self.payment_icon_ids = [Command.clear()]
     else:
         self.display_as = _("Credit Card (powered by Authorize)")
         self.payment_icon_ids = [Command.set([self.env.ref(icon_xml_id).id for icon_xml_id in (
             'payment.payment_icon_cc_maestro',
             'payment.payment_icon_cc_mastercard',
             'payment.payment_icon_cc_discover',
             'payment.payment_icon_cc_diners_club_intl',
             'payment.payment_icon_cc_jcb',
             'payment.payment_icon_cc_visa',
         )])]
Exemple #8
0
 def test_reference_is_computed_based_on_document_name(self):
     """ Test computation of reference prefixes based on the provided invoice. """
     invoice = self.env['account.move'].create({})
     reference = self.env['payment.transaction']._compute_reference(
         self.ogone.provider, invoice_ids=[Command.set([invoice.id])]
     )
     self.assertEqual(reference, 'MISC/2011/11/0001-20111102120021')
Exemple #9
0
    def invoice_transaction(self, invoice_id, access_token, **kwargs):
        """ Create a draft transaction and return its processing values.

        :param int invoice_id: The invoice to pay, as an `account.move` id
        :param str access_token: The access token used to authenticate the request
        :param dict kwargs: Locally unused data passed to `_create_transaction`
        :return: The mandatory values for the processing of the transaction
        :rtype: dict
        :raise: ValidationError if the invoice id or the access token is invalid
        """
        # Check the invoice id and the access token
        try:
            self._document_check_access('account.move', invoice_id,
                                        access_token)
        except MissingError as error:
            raise error
        except AccessError:
            raise ValidationError("The access token is invalid.")

        kwargs[
            'reference_prefix'] = None  # Allow the reference to be computed based on the invoice
        kwargs.pop('custom_create_values',
                   None)  # Don't allow passing arbitrary create values
        tx_sudo = self._create_transaction(
            custom_create_values={'invoice_ids': [Command.set([invoice_id])]},
            **kwargs,
        )

        return tx_sudo._get_processing_values()
Exemple #10
0
    def setUpClass(cls):
        super().setUpClass()

        cls.pricelist = cls.env['product.pricelist'].search(
            [('currency_id', '=', cls.currency.id)], limit=1)

        if not cls.pricelist:
            cls.pricelist = cls.env['product.pricelist'].create({
                'name':
                'Test Pricelist (%s)' % (cls.currency.name),
                'currency_id':
                cls.currency.id,
            })

        cls.sale_product = cls.env['product.product'].create({
            'sale_ok':
            True,
            'name':
            "Test Product",
        })

        cls.order = cls.env['sale.order'].create({
            'partner_id':
            cls.partner.id,
            'pricelist_id':
            cls.pricelist.id,
            'order_line': [
                Command.create({
                    'product_id': cls.sale_product.id,
                    'product_uom_qty': 5,
                    'price_unit': 20,
                })
            ],
        })
Exemple #11
0
    def portal_order_transaction(self, order_id, access_token, **kwargs):
        """ Create a draft transaction and return its processing values.

        :param int order_id: The sales order to pay, as a `sale.order` id
        :param str access_token: The access token used to authenticate the request
        :param dict kwargs: Locally unused data passed to `_create_transaction`
        :return: The mandatory values for the processing of the transaction
        :rtype: dict
        :raise: ValidationError if the invoice id or the access token is invalid
        """
        # Check the order id and the access token
        try:
            self._document_check_access('sale.order', order_id, access_token)
        except MissingError as error:
            raise error
        except AccessError:
            raise ValidationError("The access token is invalid.")

        kwargs.update({
            'reference_prefix':
            None,  # Allow the reference to be computed based on the order
            'sale_order_id':
            order_id,  # Include the SO to allow Subscriptions tokenizing the tx
        })
        kwargs.pop('custom_create_values',
                   None)  # Don't allow passing arbitrary create values
        tx_sudo = self._create_transaction(
            custom_create_values={'sale_order_ids': [Command.set([order_id])]},
            **kwargs,
        )

        return tx_sudo._get_processing_values()
Exemple #12
0
    def test_so_create_multicompany(self):
        """Check that only taxes of the right company are applied on the lines."""

        # Preparing test Data
        product_shared = self.env['product.template'].create({
            'name': 'shared product',
            'invoice_policy': 'order',
            'taxes_id': [(6, False, (self.company_data['default_tax_sale'] + self.company_data_2['default_tax_sale']).ids)],
            'property_account_income_id': self.company_data['default_account_revenue'].id,
        })

        so_1 = self.env['sale.order'].with_user(self.company_data['default_user_salesman']).create({
            'partner_id': self.env['res.partner'].create({'name': 'A partner'}).id,
            'company_id': self.company_data['company'].id,
        })
        so_1.write({
            'order_line': [Command.create({'product_id': product_shared.product_variant_id.id, 'order_id': so_1.id})],
        })
        self.assertEqual(so_1.order_line.product_uom_qty, 1)

        self.assertEqual(so_1.order_line.tax_id, self.company_data['default_tax_sale'],
            'Only taxes from the right company are put by default')
        so_1.action_confirm()
        # i'm not interested in groups/acls, but in the multi-company flow only
        # the sudo is there for that and does not impact the invoice that gets created
        # the goal here is to invoice in company 1 (because the order is in company 1) while being
        # 'mainly' in company 2 (through the context), the invoice should be in company 1
        inv=so_1.sudo()\
            .with_context(allowed_company_ids=(self.company_data['company'] + self.company_data_2['company']).ids)\
            ._create_invoices()
        self.assertEqual(inv.company_id, self.company_data['company'], 'invoices should be created in the company of the SO, not the main company of the context')
Exemple #13
0
    def _create_transaction(self,
                            *args,
                            sale_order_id=None,
                            custom_create_values=None,
                            **kwargs):
        """ Override of payment to add the sale order id in the custom create values.

        :param int sale_order_id: The sale order for which a payment id made, as a `sale.order` id
        :param dict custom_create_values: Additional create values overwriting the default ones
        :return: The result of the parent method
        :rtype: recordset of `payment.transaction`
        """
        if sale_order_id:
            if custom_create_values is None:
                custom_create_values = {}
            # As this override is also called if the flow is initiated from sale or website_sale, we
            # need not to override whatever value these modules could have already set
            if 'sale_order_ids' not in custom_create_values:  # We are in the payment module's flow
                custom_create_values['sale_order_ids'] = [
                    Command.set([int(sale_order_id)])
                ]

        return super()._create_transaction(
            *args,
            sale_order_id=sale_order_id,
            custom_create_values=custom_create_values,
            **kwargs)
Exemple #14
0
    def test_log_timesheet_with_analytic_tags(self):
        """ Test whether the analytic tag of the project or task is set on the timesheet.

            Test Case:
            ----------
                1) Create analytic tags
                2) Add analytic tag in project
                3) Create timesheet
                4) Check the default analytic tag of the project and timesheet
                5) Add analytic tag in task
                6) Check the analytic tag of the timesheet and task
        """
        Timesheet = self.env['account.analytic.line']

        share_capital_tag, office_furn_tag = self.env[
            'account.analytic.tag'].create([
                {
                    'name': 'Share capital'
                },
                {
                    'name': 'Office Furniture'
                },
            ])

        self.project_customer.analytic_tag_ids = [
            Command.set((share_capital_tag + office_furn_tag).ids)
        ]

        timesheet = Timesheet.create({
            'project_id': self.project_customer.id,
            'name': 'my first timesheet',
            'unit_amount': 4,
        })
        self.assertEqual(timesheet.tag_ids,
                         self.project_customer.analytic_tag_ids)

        self.task2.analytic_tag_ids = [
            Command.set((share_capital_tag + office_furn_tag).ids)
        ]

        timesheet1 = Timesheet.create({
            'project_id': self.project_customer.id,
            'task_id': self.task2.id,
            'name': 'my first timesheet',
            'unit_amount': 4,
        })
        self.assertEqual(timesheet1.tag_ids, self.task2.analytic_tag_ids)
Exemple #15
0
 def _compute_triggering_answer_ids(self):
     for step in self.filtered('triggering_answer_ids'):
         update_command = [
             Command.unlink(answer.id)
             for answer in step.triggering_answer_ids
             if answer.script_step_id.sequence >= step.sequence
         ]
         if update_command:
             step.triggering_answer_ids = update_command
Exemple #16
0
    def test_mailing_test_equals_reality(self):
        """
        Check that both test and real emails will format the qweb and inline placeholders correctly in body and subject.
        """
        contact_list = self.env['mailing.list'].create({
            'name':
            'Testers',
            'contact_ids': [
                Command.create({
                    'name': 'Mitchell Admin',
                    'email': '*****@*****.**',
                })
            ],
        })

        mailing = self.env['mailing.mailing'].create({
            'name':
            'TestButton',
            'subject':
            'Subject {{ object.name }} <t t-out="object.name"/>',
            'state':
            'draft',
            'mailing_type':
            'mail',
            'body_html':
            '<p>Hello {{ object.name }} <t t-out="object.name"/></p>',
            'mailing_model_id':
            self.env['ir.model']._get('mailing.list').id,
            'contact_list_ids': [contact_list.id],
        })
        mailing_test = self.env['mailing.mailing.test'].create({
            'email_to':
            '*****@*****.**',
            'mass_mailing_id':
            mailing.id,
        })

        with self.mock_mail_gateway():
            mailing_test.send_mail_test()

        expected_subject = 'Subject Mitchell Admin <t t-out="object.name"/>'
        expected_body = 'Hello {{ object.name }} Mitchell Admin'

        self.assertSentEmail(self.env.user.partner_id, ['*****@*****.**'],
                             subject=expected_subject,
                             body_content=expected_body)

        with self.mock_mail_gateway():
            # send the mailing
            mailing.action_launch()
            self.env.ref('mass_mailing.ir_cron_mass_mailing_queue'
                         ).method_direct_trigger()

        self.assertSentEmail(self.env.user.partner_id, ['*****@*****.**'],
                             subject=expected_subject,
                             body_content=expected_body)
Exemple #17
0
    def test_task_dependencies(self):
        """ Test the task dependencies feature

            Test Case:
            =========
            1) Add task2 as dependency in task1
            2) Checks if the task1 has the task in depend_on_ids field.
        """
        self.assertEqual(len(self.task_1.depend_on_ids), 0,
                         "The task 1 should not have any dependency.")
        self.task_1.write({
            'depend_on_ids': [Command.link(self.task_2.id)],
        })
        self.assertEqual(len(self.task_1.depend_on_ids), 1,
                         "The task 1 should have a dependency.")
        self.task_1.write({
            'depend_on_ids': [Command.link(self.task_3.id)],
        })
        self.assertEqual(len(self.task_1.depend_on_ids), 2,
                         "The task 1 should have two dependencies.")
Exemple #18
0
 def test_light_sales_orders_batch_creation_perf_without_taxes(self):
     self.products[0].taxes_id = [Command.set([])]
     with self.assertQueryCount(admin=59):
         self.env['sale.order'].create([{
             'partner_id': self.partners[0].id,
             'user_id': self.salesmans[0].id,
             "order_line": [
                 (0, 0, {"display_type": "line_note", "name": "NOTE"}),
                 (0, 0, {"display_type": "line_section", "name": "SECTION"}),
                 (0, 0, {'product_id': self.products[0].id})
             ]
         } for i in range(2)])
Exemple #19
0
    def test_so_tax_mapping(self):
        uom = self.env['uom.uom'].search([('name', '=', 'Units')], limit=1)
        pricelist = self.env['product.pricelist'].search(
            [('name', '=', 'Public Pricelist')], limit=1)

        partner = self.env['res.partner'].create(dict(name="George"))
        tax_include = self.env['account.tax'].create(
            dict(name="Include tax",
                 amount='21.00',
                 price_include=True,
                 type_tax_use='sale'))
        tax_exclude = self.env['account.tax'].create(
            dict(name="Exclude tax", amount='0.00', type_tax_use='sale'))

        product_tmpl = self.env['product.template'].create(
            dict(name="Voiture",
                 list_price=121,
                 taxes_id=[(6, 0, [tax_include.id])]))

        product = product_tmpl.product_variant_id

        fpos = self.env['account.fiscal.position'].create(
            dict(name="fiscal position", sequence=1))
        self.env['account.fiscal.position.tax'].create({
            'position_id':
            fpos.id,
            'tax_src_id':
            tax_include.id,
            'tax_dest_id':
            tax_exclude.id,
        })

        sale_order = self.env['sale.order'].create({
            'partner_id':
            partner.id,
            'pricelist_id':
            pricelist.id,
            'fiscal_position_id':
            fpos.id,
            'order_line': [
                Command.create({
                    'product_id': product.id,
                    'product_uom': uom.id,
                })
            ]
        })

        # Check the unit price of SO line
        self.assertEqual(100, sale_order.order_line[0].price_unit,
                         "The included tax must be subtracted to the price")
Exemple #20
0
 def create_invoice(cls, **kwargs):
     return (cls.env['account.move'].with_context(
         edi_test_mode=True).create({
             'move_type':
             'out_invoice',
             'partner_id':
             cls.partner_a.id,
             'invoice_date':
             '2022-03-15',
             'date':
             '2022-03-15',
             **kwargs, 'invoice_line_ids': [
                 Command.create({
                     **line_vals,
                 }) for line_vals in kwargs.get('invoice_line_ids', [])
             ]
         }))
Exemple #21
0
    def test_pricelist_application(self):
        """ Test different prices are correctly applied based on dates """
        support_product = self.env['product.product'].create({
            'name': 'Virtual Home Staging',
            'list_price': 100,
        })
        partner = self.env['res.partner'].create(dict(name="George"))

        christmas_pricelist = self.env['product.pricelist'].create({
            'name': 'Christmas pricelist',
            'item_ids': [(0, 0, {
                'date_start': "2017-12-01",
                'date_end': "2017-12-24",
                'compute_price': 'percentage',
                'base': 'list_price',
                'percent_price': 20,
                'applied_on': '3_global',
                'name': 'Pre-Christmas discount'
            }), (0, 0, {
                'date_start': "2017-12-25",
                'date_end': "2017-12-31",
                'compute_price': 'percentage',
                'base': 'list_price',
                'percent_price': 50,
                'applied_on': '3_global',
                'name': 'Post-Christmas super-discount'
            })]
        })

        # Create the SO with pricelist based on date
        so = self.env['sale.order'].create({
            'partner_id': partner.id,
            'date_order': '2017-12-20',
            'pricelist_id': christmas_pricelist.id,
            'order_line': [Command.create({'product_id': support_product.id})]
        })
        # Check the unit price and subtotal of SO line
        self.assertEqual(so.order_line[0].price_unit, 80, "First date pricelist rule not applied")
        self.assertEqual(so.order_line[0].price_subtotal, so.order_line[0].price_unit * so.order_line[0].product_uom_qty, 'Total of SO line should be a multiplication of unit price and ordered quantity')

        # Change order date of the SO and check the unit price and subtotal of SO line
        so.date_order = '2017-12-30'
        so.update_prices()

        self.assertEqual(so.order_line[0].price_unit, 50, "Second date pricelist rule not applied")
        self.assertEqual(so.order_line[0].price_subtotal, so.order_line[0].price_unit * so.order_line[0].product_uom_qty, 'Total of SO line should be a multiplication of unit price and ordered quantity')
Exemple #22
0
    def test_tracking_dependencies(self):
        # Enable the company setting
        self.env['res.config.settings'].create({
            'group_project_task_dependencies':
            True
        }).execute()
        # `depend_on_ids` is tracked
        self.task_1.with_context(mail_notrack=True).write(
            {'depend_on_ids': [Command.link(self.task_2.id)]})
        self.cr.precommit.clear()
        # Check that changing a dependency tracked field in task_2 logs a message in task_1.
        self.task_2.write({'date_deadline':
                           date(1983, 3,
                                1)})  # + 1 message in task_1 and task_2
        self.flush_tracking()
        self.assertEqual(
            len(self.task_1.message_ids), 1,
            'Changing the deadline on task 2 should have logged a message in task 1.'
        )

        # Check that changing a dependency tracked field in task_1 does not log a message in task_2.
        self.task_1.date_deadline = date(2020, 1, 2)  # + 1 message in task_1
        self.flush_tracking()
        self.assertEqual(
            len(self.task_2.message_ids), 1,
            'Changing the deadline on task 1 should not have logged a message in task 2.'
        )

        # Check that changing a field that is not tracked at all on task 2 does not impact task 1.
        self.task_2.color = 100  # no new message
        self.flush_tracking()
        self.assertEqual(
            len(self.task_1.message_ids), 2,
            'Changing the color on task 2 should not have logged a message in task 1 since it is not tracked.'
        )

        # Check that changing multiple fields does not log more than one message.
        self.task_2.write({
            'date_deadline': date(2020, 1, 1),
            'kanban_state': 'blocked',
        })  # + 1 message in task_1 and task_2
        self.flush_tracking()
        self.assertEqual(
            len(self.task_1.message_ids), 3,
            'Changing multiple fields on task 2 should only log one message in task 1.'
        )
Exemple #23
0
    def setUpClass(cls):
        super().setUpClass()

        cls.currency_euro = cls._prepare_currency('EUR')
        cls.currency_usd = cls._prepare_currency('USD')

        cls.country_belgium = cls.env.ref('base.be')
        cls.country_france = cls.env.ref('base.fr')
        cls.europe = cls.env.ref('base.europe')

        cls.group_user = cls.env.ref('base.group_user')
        cls.group_portal = cls.env.ref('base.group_portal')
        cls.group_public = cls.env.ref('base.group_public')

        cls.admin_user = cls.env.ref('base.user_admin')
        cls.internal_user = cls.env['res.users'].create({
            'name':
            'Internal User (Test)',
            'login':
            '******',
            'password':
            '******',
            'groups_id': [Command.link(cls.group_user.id)]
        })
        cls.portal_user = cls.env['res.users'].create({
            'name':
            'Portal User (Test)',
            'login':
            '******',
            'password':
            '******',
            'groups_id': [Command.link(cls.group_portal.id)]
        })
        cls.public_user = cls.env.ref('base.public_user')

        cls.admin_partner = cls.admin_user.partner_id
        cls.internal_partner = cls.internal_user.partner_id
        cls.portal_partner = cls.portal_user.partner_id
        cls.default_partner = cls.env['res.partner'].create({
            'name':
            'Norbert Buyer',
            'lang':
            'en_US',
            'email':
            '*****@*****.**',
            'street':
            'Huge Street',
            'street2':
            '2/543',
            'phone':
            '0032 12 34 56 78',
            'city':
            'Sin City',
            'zip':
            '1000',
            'country_id':
            cls.country_belgium.id,
        })

        # Create a dummy acquirer to allow basic tests without any specific acquirer implementation
        arch = """
        <form action="dummy" method="post">
            <input type="hidden" name="view_id" t-att-value="viewid"/>
            <input type="hidden" name="user_id" t-att-value="user_id.id"/>
        </form>
        """  # We exploit the default values `viewid` and `user_id` from QWeb's rendering context
        redirect_form = cls.env['ir.ui.view'].create({
            'name': "Dummy Redirect Form",
            'type': 'qweb',
            'arch': arch,
        })
        journal = cls.env['account.journal'].search(
            [('company_id', '=', cls.env.company.id),
             ('type', 'in', ['bank', 'cash'])],
            limit=1)
        cls.dummy_acquirer = cls.env['payment.acquirer'].create({
            'name':
            "Dummy Acquirer",
            'provider':
            'none',
            'state':
            'test',
            'allow_tokenization':
            True,
            'redirect_form_view_id':
            redirect_form.id,
            'journal_id':
            journal.id,
        })

        cls.acquirer = cls.dummy_acquirer
        cls.amount = 1111.11
        cls.company = cls.env.company
        cls.currency = cls.currency_euro
        cls.partner = cls.default_partner
        cls.reference = "Test Transaction"
Exemple #24
0
 def button_update(self):
     """更新作者方法"""
     self.authors = [Command.update(author.id, {
         "name": f"❤{author.name}"
     }) for author in self.authors]
Exemple #25
0
 def button_delete(self):
     """删除一个作者"""
     if not self.authors:
         raise AccessDenied("没有更多作者了")
     author_id = self.authors[0]
     self.authors = [Command.delete(author_id.id)]
Exemple #26
0
    def test_make_billable_at_task_rate(self):
        """ Starting from a non billable project, make it billable at task rate """
        Timesheet = self.env['account.analytic.line']
        Task = self.env['project.task']
        # set a customer on the project
        self.project_non_billable.write({
            'partner_id':
            self.partner_2.id,
            'timesheet_product_id':
            self.product_delivery_timesheet3,
        })
        # create a task and 2 timesheets
        task = Task.with_context(
            default_project_id=self.project_non_billable.id).create({
                'name':
                'first task',
                'partner_id':
                self.project_non_billable.partner_id.id,
                'planned_hours':
                10,
            })
        timesheet1 = Timesheet.create({
            'name': 'Test Line',
            'project_id': task.project_id.id,
            'task_id': task.id,
            'unit_amount': 3,
            'employee_id': self.employee_manager.id,
        })
        timesheet2 = Timesheet.create({
            'name': 'Test Line tde',
            'project_id': task.project_id.id,
            'task_id': task.id,
            'unit_amount': 2,
            'employee_id': self.employee_tde.id,
        })

        # Change project to billable at task rate
        self.project_non_billable.write({
            'allow_billable': True,
        })

        # create wizard
        wizard = self.env['project.create.sale.order'].with_context(
            active_id=self.project_non_billable.id,
            active_model='project.project').create({
                'line_ids': [
                    Command.create({
                        'product_id':
                        self.product_delivery_timesheet3.id,
                        'price_unit':
                        self.product_delivery_timesheet3.lst_price
                    }),
                ],
            })

        self.assertEqual(
            wizard.partner_id, self.project_non_billable.partner_id,
            "The wizard should have the same partner as the project")
        self.assertEqual(len(wizard.line_ids), 1,
                         "The wizard should have one line")
        self.assertEqual(wizard.line_ids.product_id,
                         self.product_delivery_timesheet3,
                         "The wizard should have one line with right product")

        # create the SO from the project
        action = wizard.action_create_sale_order()
        sale_order = self.env['sale.order'].browse(action['res_id'])

        self.assertEqual(
            sale_order.partner_id, self.project_non_billable.partner_id,
            "The customer of the SO should be the same as the project")
        self.assertEqual(len(sale_order.order_line), 1,
                         "The SO should have 1 line")
        self.assertEqual(
            sale_order.order_line.product_id, wizard.line_ids.product_id,
            "The product of the only SOL should be the selected on the wizard")
        self.assertEqual(sale_order.order_line.project_id,
                         self.project_non_billable,
                         "SOL should be linked to the project")
        self.assertTrue(
            sale_order.order_line.task_id,
            "The SOL creates a task as they were no task already present in the project (system limitation)"
        )
        self.assertEqual(sale_order.order_line.task_id.project_id,
                         self.project_non_billable,
                         "The created task should be in the project")
        self.assertEqual(
            sale_order.order_line.qty_delivered,
            timesheet1.unit_amount + timesheet2.unit_amount,
            "The create SOL should have an delivered quantity equals to the sum of tasks'timesheets"
        )
        self.assertEqual(
            self.project_non_billable.pricing_type, 'fixed_rate',
            'The pricing type of the project should be project rate since we linked a SO in the project.'
        )
Exemple #27
0
 def button_clear(self):
     """"删除所有作者"""
     self.authors = [Command.clear()]
Exemple #28
0
    def setUpClass(cls, chart_template_ref=None):
        super().setUpClass(chart_template_ref=chart_template_ref)

        Method_get_payment_method_information = AccountPaymentMethod._get_payment_method_information

        def _get_payment_method_information(self):
            res = Method_get_payment_method_information(self)
            res['none'] = {'mode': 'multi', 'domain': [('type', '=', 'bank')]}
            return res

        cls.currency_euro = cls._prepare_currency('EUR')
        cls.currency_usd = cls._prepare_currency('USD')

        cls.country_belgium = cls.env.ref('base.be')
        cls.country_france = cls.env.ref('base.fr')
        cls.europe = cls.env.ref('base.europe')

        cls.group_user = cls.env.ref('base.group_user')
        cls.group_portal = cls.env.ref('base.group_portal')
        cls.group_public = cls.env.ref('base.group_public')

        cls.admin_user = cls.env.ref('base.user_admin')
        cls.internal_user = cls.env['res.users'].create({
            'name':
            'Internal User (Test)',
            'login':
            '******',
            'password':
            '******',
            'groups_id': [Command.link(cls.group_user.id)]
        })
        cls.portal_user = cls.env['res.users'].create({
            'name':
            'Portal User (Test)',
            'login':
            '******',
            'password':
            '******',
            'groups_id': [Command.link(cls.group_portal.id)]
        })
        cls.public_user = cls.env.ref('base.public_user')

        cls.admin_partner = cls.admin_user.partner_id
        cls.internal_partner = cls.internal_user.partner_id
        cls.portal_partner = cls.portal_user.partner_id
        cls.default_partner = cls.env['res.partner'].create({
            'name':
            'Norbert Buyer',
            'lang':
            'en_US',
            'email':
            '*****@*****.**',
            'street':
            'Huge Street',
            'street2':
            '2/543',
            'phone':
            '0032 12 34 56 78',
            'city':
            'Sin City',
            'zip':
            '1000',
            'country_id':
            cls.country_belgium.id,
        })

        # Create a dummy acquirer to allow basic tests without any specific acquirer implementation
        arch = """
        <form action="dummy" method="post">
            <input type="hidden" name="view_id" t-att-value="viewid"/>
            <input type="hidden" name="user_id" t-att-value="user_id.id"/>
        </form>
        """  # We exploit the default values `viewid` and `user_id` from QWeb's rendering context
        redirect_form = cls.env['ir.ui.view'].create({
            'name': "Dummy Redirect Form",
            'type': 'qweb',
            'arch': arch,
        })

        with patch.object(AccountPaymentMethod,
                          '_get_payment_method_information',
                          _get_payment_method_information):
            cls.env['account.payment.method'].create({
                'name': 'Dummy method',
                'code': 'none',
                'payment_type': 'inbound'
            })
        cls.dummy_acquirer = cls.env['payment.acquirer'].create({
            'name':
            "Dummy Acquirer",
            'provider':
            'none',
            'state':
            'test',
            'allow_tokenization':
            True,
            'redirect_form_view_id':
            redirect_form.id,
            'journal_id':
            cls.company_data['default_journal_bank'].id,
        })

        cls.acquirer = cls.dummy_acquirer
        cls.amount = 1111.11
        cls.company = cls.env.company
        cls.currency = cls.currency_euro
        cls.partner = cls.default_partner
        cls.reference = "Test Transaction"
        cls.account = cls.company.account_journal_payment_credit_account_id
        cls.invoice = cls.env['account.move'].create({
            'move_type':
            'entry',
            'date':
            '2019-01-01',
            'line_ids': [
                (0, 0, {
                    'account_id': cls.account.id,
                    'currency_id': cls.currency_euro.id,
                    'debit': 100.0,
                    'credit': 0.0,
                    'amount_currency': 200.0,
                }),
                (0, 0, {
                    'account_id': cls.account.id,
                    'currency_id': cls.currency_euro.id,
                    'debit': 0.0,
                    'credit': 100.0,
                    'amount_currency': -200.0,
                }),
            ],
        })
Exemple #29
0
 def button_create(self):
     """创建作者方法"""
     self.authors = [Command.create({
         "name": "瑶瑶"
     })]
Exemple #30
0
    def _create_transaction(
        self, payment_option_id, reference_prefix, amount, currency_id, partner_id, flow,
        tokenization_requested, landing_route, is_validation=False, invoice_id=None,
        custom_create_values=None, **kwargs
    ):
        """ Create a draft transaction based on the payment context and return it.

        :param int payment_option_id: The payment option handling the transaction, as a
                                      `payment.acquirer` id or a `payment.token` id
        :param str reference_prefix: The custom prefix to compute the full reference
        :param float|None amount: The amount to pay in the given currency.
                                  None if in a payment method validation operation
        :param int|None currency_id: The currency of the transaction, as a `res.currency` id.
                                     None if in a payment method validation operation
        :param int partner_id: The partner making the payment, as a `res.partner` id
        :param str flow: The online payment flow of the transaction: 'redirect', 'direct' or 'token'
        :param bool tokenization_requested: Whether the user requested that a token is created
        :param str landing_route: The route the user is redirected to after the transaction
        :param bool is_validation: Whether the operation is a validation
        :param int invoice_id: The account move for which a payment id made, as an `account.move` id
        :param dict custom_create_values: Additional create values overwriting the default ones
        :param dict kwargs: Locally unused data passed to `_is_tokenization_required` and
                            `_compute_reference`
        :return: The sudoed transaction that was created
        :rtype: recordset of `payment.transaction`
        :raise: UserError if the flow is invalid
        """
        # Prepare create values
        if flow in ['redirect', 'direct']:  # Direct payment or payment with redirection
            acquirer_sudo = request.env['payment.acquirer'].sudo().browse(payment_option_id)
            token_id = None
            tokenization_required_or_requested = acquirer_sudo._is_tokenization_required(
                provider=acquirer_sudo.provider, **kwargs
            ) or tokenization_requested
            tokenize = bool(
                # Don't tokenize if the user tried to force it through the browser's developer tools
                acquirer_sudo.allow_tokenization
                # Token is only created if required by the flow or requested by the user
                and tokenization_required_or_requested
            )
        elif flow == 'token':  # Payment by token
            token_sudo = request.env['payment.token'].sudo().browse(payment_option_id)

            # Prevent from paying with a token that doesn't belong to the current partner (either
            # the current user's partner if logged in, or the partner on behalf of whom the payment
            # is being made).
            partner_sudo = request.env['res.partner'].sudo().browse(partner_id)
            if partner_sudo.commercial_partner_id != token_sudo.partner_id.commercial_partner_id:
                raise AccessError(_("You do not have access to this payment token."))

            acquirer_sudo = token_sudo.acquirer_id
            token_id = payment_option_id
            tokenize = False
        else:
            raise UserError(
                _("The payment should either be direct, with redirection, or made by a token.")
            )

        if invoice_id:
            if custom_create_values is None:
                custom_create_values = {}
            custom_create_values['invoice_ids'] = [Command.set([int(invoice_id)])]

        reference = request.env['payment.transaction']._compute_reference(
            acquirer_sudo.provider,
            prefix=reference_prefix,
            **(custom_create_values or {}),
            **kwargs
        )
        if is_validation:  # Acquirers determine the amount and currency in validation operations
            amount = acquirer_sudo._get_validation_amount()
            currency_id = acquirer_sudo._get_validation_currency().id

        # Create the transaction
        tx_sudo = request.env['payment.transaction'].sudo().create({
            'acquirer_id': acquirer_sudo.id,
            'reference': reference,
            'amount': amount,
            'currency_id': currency_id,
            'partner_id': partner_id,
            'token_id': token_id,
            'operation': f'online_{flow}' if not is_validation else 'validation',
            'tokenize': tokenize,
            'landing_route': landing_route,
            **(custom_create_values or {}),
        })  # In sudo mode to allow writing on callback fields

        if flow == 'token':
            tx_sudo._send_payment_request()  # Payments by token process transactions immediately
        else:
            tx_sudo._log_sent_message()

        # Monitor the transaction to make it available in the portal
        PaymentPostProcessing.monitor_transactions(tx_sudo)

        return tx_sudo