예제 #1
0
    def test_calendar_working_day_intervals_leaves_generic(self):
        # Test: day0 with leaves outside range: 1 interval
        intervals = self.calendar._get_day_work_intervals(
            Date.from_string('2013-02-12'),
            start_time=time(7, 0, 0),
            compute_leaves=True)
        self.assertEqual(len(intervals), 1)
        self.assertEqual(intervals[0][:2],
                         (Datetime.from_string('2013-02-12 08:00:00'),
                          Datetime.from_string('2013-02-12 16:00:00')))

        # Test: day0 with leaves: 2 intervals because of leave between 9 and 12, ending at 15:45:30
        intervals = self.calendar._get_day_work_intervals(
            Date.from_string('2013-02-19'),
            start_time=time(8, 15, 0),
            end_time=time(15, 45, 30),
            compute_leaves=True)
        self.assertEqual(len(intervals), 2)
        self.assertEqual(intervals[0][:2],
                         (Datetime.from_string('2013-02-19 08:15:00'),
                          Datetime.from_string('2013-02-19 09:00:00')))
        self.assertEqual(intervals[1][:2],
                         (Datetime.from_string('2013-02-19 12:00:00'),
                          Datetime.from_string('2013-02-19 15:45:30')))
        self.assertEqual(intervals[0][2]['attendances'], self.att_1)
        self.assertEqual(intervals[0][2]['leaves'], self.leave1)
        self.assertEqual(intervals[1][2]['attendances'], self.att_1)
        self.assertEqual(intervals[0][2]['leaves'], self.leave1)
예제 #2
0
    def setUp(self):
        super(TestPayslipBase, self).setUp()

        # Some salary rules references
        self.hra_rule_id = self.ref(
            'hr_payroll.hr_salary_rule_houserentallowance1')
        self.conv_rule_id = self.ref(
            'hr_payroll.hr_salary_rule_convanceallowance1')
        self.prof_tax_rule_id = self.ref(
            'hr_payroll.hr_salary_rule_professionaltax1')
        self.pf_rule_id = self.ref('hr_payroll.hr_salary_rule_providentfund1')
        self.mv_rule_id = self.ref('hr_payroll.hr_salary_rule_meal_voucher')
        self.comm_rule_id = self.ref(
            'hr_payroll.hr_salary_rule_sales_commission')

        # I create a new employee "Richard"
        self.richard_emp = self.env['hr.employee'].create({
            'name':
            'Richard',
            'gender':
            'male',
            'birthday':
            '1984-05-01',
            'country_id':
            self.ref('base.be'),
            'department_id':
            self.ref('hr.dep_rd')
        })

        # I create a salary structure for "Software Developer"
        self.developer_pay_structure = self.env['hr.payroll.structure'].create(
            {
                'name':
                'Salary Structure for Software Developer',
                'code':
                'SD',
                'company_id':
                self.ref('base.main_company'),
                'rule_ids': [(4, self.hra_rule_id), (4, self.conv_rule_id),
                             (4, self.prof_tax_rule_id), (4, self.pf_rule_id),
                             (4, self.mv_rule_id), (4, self.comm_rule_id)],
            })

        # I create a contract for "Richard"
        self.env['hr.contract'].create({
            'date_end':
            Date.to_string((datetime.now() + timedelta(days=365))),
            'date_start':
            Date.today(),
            'name':
            'Contract for Richard',
            'wage':
            5000.0,
            'type_id':
            self.ref('hr_contract_types.hr_contract_type_emp'),
            'employee_id':
            self.richard_emp.id,
            'struct_id':
            self.developer_pay_structure.id,
        })
예제 #3
0
    def test_calendar_working_day_intervals_no_leaves(self):
        # Test: day0 without leaves: 1 interval
        intervals = self.calendar._get_day_work_intervals(
            Date.from_string('2013-02-12'), start_time=time(9, 8, 7))
        self.assertEqual(len(intervals), 1)
        self.assertEqual(intervals[0][:2],
                         (Datetime.from_string('2013-02-12 09:08:07'),
                          Datetime.from_string('2013-02-12 16:00:00')))
        self.assertEqual(intervals[0][2]['attendances'], self.att_1)

        # Test: day1, beginning at 10:30 -> work from 10:30 (arrival) until 16:00
        intervals = self.calendar._get_day_work_intervals(
            Date.from_string('2013-02-19'), start_time=time(10, 30, 0))
        self.assertEqual(len(intervals), 1)
        self.assertEqual(intervals[0][:2],
                         (Datetime.from_string('2013-02-19 10:30:00'),
                          Datetime.from_string('2013-02-19 16:00:00')))
        self.assertEqual(intervals[0][2]['attendances'], self.att_1)

        # Test: day3 without leaves: 2 interval
        intervals = self.calendar._get_day_work_intervals(
            Date.from_string('2013-02-15'), start_time=time(10, 11, 12))
        self.assertEqual(len(intervals), 2)
        self.assertEqual(intervals[0][:2],
                         (Datetime.from_string('2013-02-15 10:11:12'),
                          Datetime.from_string('2013-02-15 13:00:00')))
        self.assertEqual(intervals[1][:2],
                         (Datetime.from_string('2013-02-15 16:00:00'),
                          Datetime.from_string('2013-02-15 23:00:00')))
        self.assertEqual(intervals[0][2]['attendances'], self.att_2)
        self.assertEqual(intervals[1][2]['attendances'], self.att_3)
예제 #4
0
    def setUpClass(cls):
        super(TestContractCalendars, cls).setUpClass()
        cls.calendar_richard = cls.env['resource.calendar'].create({'name': 'Calendar of Richard'})
        cls.employee.resource_calendar_id = cls.calendar_richard

        cls.calendar_35h = cls.env['resource.calendar'].create({'name': '35h calendar'})
        cls.calendar_35h._onchange_hours_per_day()  # update hours/day

        cls.contract_cdd = cls.env['hr.contract'].create({
            'date_end': Date.to_date('2015-11-15'),
            'date_start': Date.to_date('2015-01-01'),
            'name': 'First CDD Contract for Richard',
            'resource_calendar_id': cls.calendar_35h.id,
            'wage': 5000.0,
            'employee_id': cls.employee.id,
            'state': 'close',
        })
예제 #5
0
    def test_01_test_total(self):
        today_date = Date.today()
        last_year_date = Date.to_string(datetime.today() -
                                        relativedelta(years=1))

        move1 = self._add_move(today_date, self.journal_sale, 0, 100, 100, 0)
        move2 = self._add_move(last_year_date, self.journal_sale, 0, 100, 100,
                               0)

        report = self.ReportJournalLedger.create({
            'date_from':
            self.fy_date_start,
            'date_to':
            self.fy_date_end,
            'company_id':
            self.company.id,
            'journal_ids': [(6, 0, self.journal_sale.ids)]
        })
        report.compute_data_for_report()

        self.check_report_journal_debit_credit(report, 100, 100)

        move3 = self._add_move(today_date, self.journal_sale, 0, 100, 100, 0)

        report.compute_data_for_report()
        self.check_report_journal_debit_credit(report, 200, 200)

        report.move_target = 'posted'
        report.compute_data_for_report()
        self.check_report_journal_debit_credit(report, 0, 0)

        move1.post()
        report.compute_data_for_report()
        self.check_report_journal_debit_credit(report, 100, 100)

        move2.post()
        report.compute_data_for_report()
        self.check_report_journal_debit_credit(report, 100, 100)

        move3.post()
        report.compute_data_for_report()
        self.check_report_journal_debit_credit(report, 200, 200)

        report.date_from = self.previous_fy_date_start
        report.compute_data_for_report()
        self.check_report_journal_debit_credit(report, 300, 300)
예제 #6
0
 def test_calendar_working_day_intervals_leaves_resource(self):
     # Test: day1+14 on leave, with resource leave computation
     intervals = self.calendar._get_day_work_intervals(
         Date.from_string('2013-02-26'),
         start_time=time(7, 0, 0),
         compute_leaves=True,
         resource_id=self.resource1_id)
     # Result: nothing, because on leave
     self.assertEqual(len(intervals), 0)
예제 #7
0
    def test_calendar_previous_day(self):
        # Test: previous day: previous day before day1 is (day4-7)
        date = self.calendar._get_previous_work_day(
            day_date=Date.from_string('2013-02-12'))
        self.assertEqual(date, self.date2.date() + relativedelta(days=-7))

        # Test: previous day: previous day before day4 is day1
        date = self.calendar._get_previous_work_day(
            day_date=Date.from_string('2013-02-15'))
        self.assertEqual(date, self.date1.date())

        # Test: previous day: previous day before day4+1 is day4
        date = self.calendar._get_previous_work_day(
            day_date=Date.from_string('2013-02-15') + relativedelta(days=1))
        self.assertEqual(date, self.date2.date())

        # Test: previous day: previous day before day1-1 is (day4-7)
        date = self.calendar._get_previous_work_day(
            day_date=Date.from_string('2013-02-12') + relativedelta(days=-1))
        self.assertEqual(date, self.date2.date() + relativedelta(days=-7))
예제 #8
0
    def test_calendar_next_day(self):
        # Test: next day: next day after day1 is day4
        date = self.calendar._get_next_work_day(
            day_date=Date.from_string('2013-02-12'))
        self.assertEqual(date, self.date2.date())

        # Test: next day: next day after day4 is (day1+7)
        date = self.calendar._get_next_work_day(
            day_date=Date.from_string('2013-02-15'))
        self.assertEqual(date, self.date1.date() + relativedelta(days=7))

        # Test: next day: next day after day4+1 is (day1+7)
        date = self.calendar._get_next_work_day(
            day_date=Date.from_string('2013-02-15') + relativedelta(days=1))
        self.assertEqual(date, self.date1.date() + relativedelta(days=7))

        # Test: next day: next day after day1-1 is day1
        date = self.calendar._get_next_work_day(
            day_date=Date.from_string('2013-02-12') + relativedelta(days=-1))
        self.assertEqual(date, self.date1.date())
예제 #9
0
    def test_program_rules_validity_dates_and_uses(self):
        # Test case: Based on the validity dates and the number of allowed uses

        self.immediate_promotion_program.write({
            'rule_date_from':
            Date.to_string((datetime.now() - timedelta(days=7))),
            'rule_date_to':
            Date.to_string((datetime.now() - timedelta(days=2))),
            'maximum_use_number':
            1,
        })

        order = self.empty_order
        order.write({
            'order_line': [(0, False, {
                'product_id': self.product_A.id,
                'name': '1 Product A',
                'product_uom': self.uom_unit.id,
                'product_uom_qty': 1.0,
            }),
                           (0, False, {
                               'product_id': self.product_B.id,
                               'name': '2 Product B',
                               'product_uom': self.uom_unit.id,
                               'product_uom_qty': 1.0,
                           })]
        })
        order.recompute_coupon_lines()
        self.assertEqual(
            len(order.order_line.ids), 2,
            "The promo offert shouldn't have been applied we're not between the validity dates"
        )

        self.immediate_promotion_program.write({
            'rule_date_from':
            Date.to_string((datetime.now() - timedelta(days=7))),
            'rule_date_to':
            Date.to_string((datetime.now() + timedelta(days=2))),
        })
        order = self.env['sale.order'].create({'partner_id': self.steve.id})
        order.write({
            'order_line': [(0, False, {
                'product_id': self.product_A.id,
                'name': '1 Product A',
                'product_uom': self.uom_unit.id,
                'product_uom_qty': 10.0,
            }),
                           (0, False, {
                               'product_id': self.product_B.id,
                               'name': '2 Product B',
                               'product_uom': self.uom_unit.id,
                               'product_uom_qty': 1.0,
                           })]
        })
        order.recompute_coupon_lines()
        self.assertEqual(
            len(order.order_line.ids), 3,
            "The promo offert should have been applied as we're between the validity dates"
        )
        order = self.env['sale.order'].create({
            'partner_id':
            self.env['res.partner'].create({
                'name': 'My Partner'
            }).id
        })
        order.write({
            'order_line': [(0, False, {
                'product_id': self.product_A.id,
                'name': '1 Product A',
                'product_uom': self.uom_unit.id,
                'product_uom_qty': 10.0,
            }),
                           (0, False, {
                               'product_id': self.product_B.id,
                               'name': '2 Product B',
                               'product_uom': self.uom_unit.id,
                               'product_uom_qty': 1.0,
                           })]
        })
        order.recompute_coupon_lines()
        self.assertEqual(
            len(order.order_line.ids), 2,
            "The promo offert shouldn't have been applied as the number of uses is exceeded"
        )
예제 #10
0
    def test_contract_transfer_leaves(self):

        def create_calendar_leave(start, end, resource=None):
            return self.env['resource.calendar.leaves'].create({
                'name': 'leave name',
                'date_from': start,
                'date_to': end,
                'resource_id': resource.id if resource else None,
                'calendar_id': self.employee.resource_calendar_id.id,
                'time_type': 'leave',
            })

        start = Datetime.to_datetime('2015-11-17 07:00:00')
        end = Datetime.to_datetime('2015-11-20 18:00:00')
        leave1 = create_calendar_leave(start, end, resource=self.employee.resource_id)

        start = Datetime.to_datetime('2015-11-25 07:00:00')
        end = Datetime.to_datetime('2015-11-28 18:00:00')
        leave2 = create_calendar_leave(start, end, resource=self.employee.resource_id)

        # global leave
        start = Datetime.to_datetime('2015-11-25 07:00:00')
        end = Datetime.to_datetime('2015-11-28 18:00:00')
        leave3 = create_calendar_leave(start, end)

        self.calendar_richard.transfer_leaves_to(self.calendar_35h, resources=self.employee.resource_id, from_date=Date.to_date('2015-11-21'))

        self.assertEqual(leave1.calendar_id, self.calendar_richard, "It should stay in Richard's calendar")
        self.assertEqual(leave3.calendar_id, self.calendar_richard, "Global leave should stay in original calendar")
        self.assertEqual(leave2.calendar_id, self.calendar_35h, "It should be transfered to the other calendar")

        # Transfer global leaves
        self.calendar_richard.transfer_leaves_to(self.calendar_35h, resources=None, from_date=Date.to_date('2015-11-21'))

        self.assertEqual(leave3.calendar_id, self.calendar_35h, "Global leave should be transfered") 
예제 #11
0
    def test_account_budget(self):

        # Creating a crossovered.budget record
        budget = self.env['crossovered.budget'].create({
            'date_from':
            Date.from_string('%s-01-01' % (datetime.datetime.now().year + 1)),
            'date_to':
            Date.from_string('%s-12-31' % (datetime.datetime.now().year + 1)),
            'name':
            'Budget %s' % (datetime.datetime.now().year + 1),
            'state':
            'draft'
        })

        # I created two different budget lines
        # Modifying a crossovered.budget record
        self.env['crossovered.budget.lines'].create({
            'crossovered_budget_id':
            budget.id,
            'analytic_account_id':
            self.ref('analytic.analytic_partners_camp_to_camp'),
            'date_from':
            Date.from_string('%s-01-01' % (datetime.datetime.now().year + 1)),
            'date_to':
            Date.from_string('%s-12-31' % (datetime.datetime.now().year + 1)),
            'general_budget_id':
            self.account_budget_post_purchase0.id,
            'planned_amount':
            10000.0,
        })
        self.env['crossovered.budget.lines'].create({
            'crossovered_budget_id':
            budget.id,
            'analytic_account_id':
            self.ref('analytic.analytic_our_super_product'),
            'date_from':
            Date.from_string('%s-09-01' % (datetime.datetime.now().year + 1)),
            'date_to':
            Date.from_string('%s-09-30' % (datetime.datetime.now().year + 1)),
            'general_budget_id':
            self.account_budget_post_sales0.id,
            'planned_amount':
            400000.0,
        })
        # I check that Initially Budget is in "draft" state
        self.assertEqual(budget.state, 'draft')

        # I pressed the confirm button to confirm the Budget
        # Performing an action confirm on module crossovered.budget
        budget.action_budget_confirm()

        # I check that budget is in "Confirmed" state
        self.assertEqual(budget.state, 'confirm')

        # I pressed the validate button to validate the Budget
        # Performing an action validate on module crossovered.budget
        budget.action_budget_validate()

        # I check that budget is in "Validated" state
        self.assertEqual(budget.state, 'validate')

        # I pressed the done button to set the Budget to "Done" state
        # Performing an action done on module crossovered.budget
        budget.action_budget_done()

        # I check that budget is in "done" state
        self.assertEqual(budget.state, 'done')
예제 #12
0
 def dump_date(self, value, write):
     value = Date.to_string(value)
     self.dump_unicode(value, write)
예제 #13
0
    def test_kit_anglo_saxo_price_diff(self):
        """
        Suppose an automated-AVCO configuration and a Price Difference Account defined on
        the product category. When buying a kit of that category at a higher price than its
        cost, the difference should be published on the Price Difference Account
        """
        price_diff_account = self.env['account.account'].create({
            'name':
            'Super Price Difference Account',
            'code':
            'SPDA',
            'user_type_id':
            self.env.ref('account.data_account_type_current_assets').id,
            'reconcile':
            True,
        })
        self.avco_category.property_account_creditor_price_difference_categ = price_diff_account

        kit, compo01, compo02 = self.env['product.product'].create([{
            'name':
            name,
            'standard_price':
            price,
            'type':
            'product',
            'categ_id':
            self.avco_category.id,
        } for name, price in [('Kit', 0), ('Compo 01', 10), ('Compo 02', 20)]])

        self.env['mrp.bom'].create({
            'product_tmpl_id':
            kit.product_tmpl_id.id,
            'type':
            'phantom',
            'bom_line_ids': [(0, 0, {
                'product_id': p.id,
                'product_qty': 1,
            }) for p in [compo01, compo02]]
        })
        kit.button_bom_cost()

        po_form = Form(self.env['purchase.order'])
        po_form.partner_id = self.vendor01
        with po_form.order_line.new() as pol_form:
            pol_form.product_id = kit
            pol_form.price_unit = 100
        po = po_form.save()
        po.button_confirm()

        action = po.picking_ids.button_validate()
        wizard = Form(self.env[action['res_model']].with_context(
            action['context'])).save()
        wizard.process()

        action = po.action_create_invoice()
        invoice = self.env['account.move'].browse(action['res_id'])
        invoice.invoice_date = Date.today()
        invoice.action_post()
        price_diff_aml = invoice.line_ids.filtered(
            lambda l: l.account_id == price_diff_account)
        self.assertEqual(
            price_diff_aml.balance, 70,
            "Should be the purchase price minus the kit cost (i.e. 100 - 30)")
예제 #14
0
    def setUp(self):
        super(TestJournalReport, self).setUp()
        self.AccountObj = self.env['account.account']
        self.InvoiceObj = self.env['account.invoice']
        self.JournalObj = self.env['account.journal']
        self.JournalReportObj = self.env['journal.ledger.report.wizard']
        self.MoveObj = self.env['account.move']
        self.ReportJournalLedger = self.env['report_journal_ledger']
        self.TaxObj = self.env['account.tax']

        self.company = self.env.ref('base.main_company')

        today = datetime.today()
        last_year = today - relativedelta(years=1)

        self.previous_fy_date_start = Date.to_string(
            last_year.replace(month=1, day=1))
        self.previous_fy_date_end = Date.to_string(
            last_year.replace(month=12, day=31))
        self.fy_date_start = Date.to_string(today.replace(month=1, day=1))
        self.fy_date_end = Date.to_string(today.replace(month=12, day=31))

        self.receivable_account = self.AccountObj.search(
            [('user_type_id.name', '=', 'Receivable')], limit=1)
        self.income_account = self.AccountObj.search(
            [('user_type_id.name', '=', 'Income')], limit=1)
        self.payable_account = self.AccountObj.search(
            [('user_type_id.name', '=', 'Payable')], limit=1)

        self.journal_sale = self.JournalObj.create({
            'name':
            "Test journal sale",
            'code':
            "TST-JRNL-S",
            'type':
            'sale',
            'company_id':
            self.company.id,
        })
        self.journal_purchase = self.JournalObj.create({
            'name':
            "Test journal purchase",
            'code':
            "TST-JRNL-P",
            'type':
            'sale',
            'company_id':
            self.company.id,
        })

        self.tax_15_s = self.TaxObj.create({
            'sequence': 30,
            'name': 'Tax 15.0% (Percentage of Price)',
            'amount': 15.0,
            'amount_type': 'percent',
            'include_base_amount': False,
            'type_tax_use': 'sale',
        })

        self.tax_20_s = self.TaxObj.create({
            'sequence': 30,
            'name': 'Tax 20.0% (Percentage of Price)',
            'amount': 20.0,
            'amount_type': 'percent',
            'include_base_amount': False,
            'type_tax_use': 'sale',
        })

        self.tax_15_p = self.TaxObj.create({
            'sequence': 30,
            'name': 'Tax 15.0% (Percentage of Price)',
            'amount': 15.0,
            'amount_type': 'percent',
            'include_base_amount': False,
            'type_tax_use': 'purchase',
        })

        self.tax_20_p = self.TaxObj.create({
            'sequence': 30,
            'name': 'Tax 20.0% (Percentage of Price)',
            'amount': 20.0,
            'amount_type': 'percent',
            'include_base_amount': False,
            'type_tax_use': 'purchase',
        })

        self.partner_2 = self.env.ref('base.res_partner_2')
예제 #15
0
    def test_reversed_invoice_reinvoice_with_period(self):
        """
        Tests that when reversing an invoice of timesheet and selecting a time
        period, the qty to invoice is correctly found
        Business flow:
          Create a sale order and deliver some hours (invoiced = 0)
          Create an invoice
          Confirm (invoiced = 1)
          Add Credit Note
          Confirm (invoiced = 0)
          Go back to the SO
          Create an invoice
          Select a time period [1 week ago, 1 week in the future]
          Confirm
          -> Fails if there is nothing to invoice
        """
        product = self.env['product.product'].create({
            'name':
            "Service delivered, create task in global project",
            'standard_price':
            30,
            'list_price':
            90,
            'type':
            'service',
            'service_policy':
            'delivered_timesheet',
            'invoice_policy':
            'delivery',
            'default_code':
            'SERV-DELI2',
            'service_type':
            'timesheet',
            'service_tracking':
            'task_global_project',
            'project_id':
            self.project_global.id,
            'taxes_id':
            False,
            'property_account_income_id':
            self.account_sale.id,
        })
        today = Date.context_today(self.env.user)

        # Creates a sales order for quantity 3
        so_form = Form(self.env['sale.order'])
        so_form.partner_id = self.env['res.partner'].create({'name': 'Toto'})
        with so_form.order_line.new() as line:
            line.product_id = product
            line.product_uom_qty = 3.0
        sale_order = so_form.save()
        sale_order.action_confirm()

        # "Deliver" 1 of 3
        task = sale_order.tasks_ids
        self.env['account.analytic.line'].create({
            'name':
            'Test Line',
            'project_id':
            task.project_id.id,
            'task_id':
            task.id,
            'unit_amount':
            1,
            'employee_id':
            self.employee_user.id,
            'company_id':
            self.company_data['company'].id,
        })

        context = {
            "active_model": 'sale.order',
            "active_ids": [sale_order.id],
            "active_id": sale_order.id,
            'open_invoices': True,
        }
        # Invoice the 1
        wizard = self.env['sale.advance.payment.inv'].with_context(
            context).create({'advance_payment_method': 'delivered'})
        invoice_dict = wizard.create_invoices()
        # Confirm the invoice
        invoice = self.env['account.move'].browse(invoice_dict['res_id'])
        invoice.action_post()
        # Refund the invoice
        refund_invoice_wiz = self.env['account.move.reversal'].with_context(
            active_model="account.move", active_ids=[invoice.id]).create({
                'reason':
                'please reverse :c',
                'refund_method':
                'refund',
                'date':
                today,
            })
        refund_invoice = self.env['account.move'].browse(
            refund_invoice_wiz.reverse_moves()['res_id'])
        refund_invoice.action_post()
        # reversing with action_reverse and then action_post does not reset the invoice_status to 'to invoice' in tests

        # Recreate wizard to get the new invoices created
        wizard = self.env['sale.advance.payment.inv'].with_context(
            context).create({
                'advance_payment_method':
                'delivered',
                'date_start_invoice_timesheet':
                today - timedelta(days=7),
                'date_end_invoice_timesheet':
                today + timedelta(days=7)
            })

        # The actual test :
        wizard.create_invoices(
        )  # No exception should be raised, there is indeed something to be invoiced since it was reversed
예제 #16
0
    def test_transfert_project(self):
        """ Transfert task with timesheet to another project. """
        Timesheet = self.env['account.analytic.line']
        Task = self.env['project.task']
        today = Date.context_today(self.env.user)

        task = Task.with_context(
            default_project_id=self.project_global.id).create({
                'name':
                'first task',
                'partner_id':
                self.partner_a.id,
                'planned_hours':
                10,
            })

        Timesheet.create({
            'project_id': self.project_global.id,
            'task_id': task.id,
            'name': 'my first timesheet',
            'unit_amount': 4,
        })

        timesheet_count1 = Timesheet.search_count([('project_id', '=',
                                                    self.project_global.id)])
        timesheet_count2 = Timesheet.search_count([('project_id', '=',
                                                    self.project_template.id)])
        self.assertEqual(timesheet_count1, 1,
                         "One timesheet in project_global")
        self.assertEqual(timesheet_count2, 0,
                         "No timesheet in project_template")
        self.assertEqual(len(task.timesheet_ids), 1,
                         "The timesheet should be linked to task")

        # change project of task, as the timesheet is not yet invoiced, the timesheet will change his project
        task.write({'project_id': self.project_template.id})

        timesheet_count1 = Timesheet.search_count([('project_id', '=',
                                                    self.project_global.id)])
        timesheet_count2 = Timesheet.search_count([('project_id', '=',
                                                    self.project_template.id)])
        self.assertEqual(timesheet_count1, 0, "No timesheet in project_global")
        self.assertEqual(timesheet_count2, 1,
                         "One timesheet in project_template")
        self.assertEqual(len(task.timesheet_ids), 1,
                         "The timesheet still should be linked to task")

        wizard = self.env['project.task.create.sale.order'].with_context(
            active_id=task.id, active_model='project.task').create(
                {'product_id': self.product_delivery_timesheet3.id})

        # We create the SO and the invoice
        action = wizard.action_create_sale_order()
        sale_order = self.env['sale.order'].browse(action['res_id'])
        self.context = {
            'active_model': 'sale.order',
            'active_ids': [sale_order.id],
            'active_id': sale_order.id,
            'default_journal_id': self.company_data['default_journal_sale'].id
        }
        wizard = self.env['sale.advance.payment.inv'].with_context(
            self.context).create({
                'advance_payment_method':
                'delivered',
                'date_start_invoice_timesheet':
                today - timedelta(days=4),
                'date_end_invoice_timesheet':
                today
            })
        wizard.create_invoices()

        Timesheet.create({
            'project_id': self.project_template.id,
            'task_id': task.id,
            'name': 'my second timesheet',
            'unit_amount': 6,
        })

        self.assertEqual(
            Timesheet.search_count([
                ('project_id', '=', self.project_template.id)
            ]), 2, "2 timesheets in project_template")

        # change project of task, the timesheet not yet invoiced will change its project. The timesheet already invoiced will not change his project.
        task.write({'project_id': self.project_global.id})

        timesheet_count1 = Timesheet.search_count([('project_id', '=',
                                                    self.project_global.id)])
        timesheet_count2 = Timesheet.search_count([('project_id', '=',
                                                    self.project_template.id)])
        self.assertEqual(timesheet_count1, 1,
                         "One timesheet in project_global")
        self.assertEqual(timesheet_count2, 1,
                         "Still one timesheet in project_template")
        self.assertEqual(len(task.timesheet_ids), 2,
                         "The 2 timesheet still should be linked to task")
예제 #17
0
    def test_timesheet_invoice(self):
        """ Test to create invoices for the sale order with timesheets

            1) create sale order
            2) try to create an invoice for the timesheets 10 days before
            3) create invoice for the timesheets 6 days before
            4) create invoice for the timesheets 4 days before
            5) create invoice for the timesheets from today
        """
        today = Date.context_today(self.env.user)
        sale_order = self.env['sale.order'].create({
            'partner_id':
            self.partner_a.id,
            'partner_invoice_id':
            self.partner_a.id,
            'partner_shipping_id':
            self.partner_a.id,
            'pricelist_id':
            self.company_data['default_pricelist'].id,
        })
        # Section Line
        so_line_ordered_project_only = self.env['sale.order.line'].create({
            'name':
            "Section Name",
            'order_id':
            sale_order.id,
            'display_type':
            'line_section',
        })
        so_line_deliver_global_project = self.env['sale.order.line'].create({
            'name':
            self.product_delivery_timesheet2.name,
            'product_id':
            self.product_delivery_timesheet2.id,
            'product_uom_qty':
            50,
            'product_uom':
            self.product_delivery_timesheet2.uom_id.id,
            'price_unit':
            self.product_delivery_timesheet2.list_price,
            'order_id':
            sale_order.id,
        })
        so_line_deliver_task_project = self.env['sale.order.line'].create({
            'name':
            self.product_delivery_timesheet3.name,
            'product_id':
            self.product_delivery_timesheet3.id,
            'product_uom_qty':
            20,
            'product_uom':
            self.product_delivery_timesheet3.uom_id.id,
            'price_unit':
            self.product_delivery_timesheet3.list_price,
            'order_id':
            sale_order.id,
        })
        so_line_deliver_global_project.product_id_change()
        so_line_deliver_task_project.product_id_change()

        # confirm SO
        sale_order.action_confirm()
        task_serv1 = self.env['project.task'].search([
            ('sale_line_id', '=', so_line_deliver_global_project.id)
        ])
        task_serv2 = self.env['project.task'].search([
            ('sale_line_id', '=', so_line_deliver_task_project.id)
        ])
        project_serv2 = self.env['project.project'].search([
            ('sale_line_id', '=', so_line_deliver_task_project.id)
        ])

        timesheet1 = self.env['account.analytic.line'].create({
            'name':
            'Test Line',
            'project_id':
            task_serv1.project_id.id,
            'task_id':
            task_serv1.id,
            'unit_amount':
            10,
            'employee_id':
            self.employee_manager.id,
            'date':
            today - timedelta(days=6)
        })

        timesheet2 = self.env['account.analytic.line'].create({
            'name':
            'Test Line 2',
            'project_id':
            task_serv1.project_id.id,
            'task_id':
            task_serv1.id,
            'unit_amount':
            20,
            'employee_id':
            self.employee_manager.id,
            'date':
            today - timedelta(days=1)
        })

        timesheet3 = self.env['account.analytic.line'].create({
            'name':
            'Test Line 3',
            'project_id':
            task_serv1.project_id.id,
            'task_id':
            task_serv1.id,
            'unit_amount':
            10,
            'employee_id':
            self.employee_manager.id,
            'date':
            today - timedelta(days=5)
        })

        timesheet4 = self.env['account.analytic.line'].create({
            'name':
            'Test Line 4',
            'project_id':
            task_serv2.project_id.id,
            'task_id':
            task_serv2.id,
            'unit_amount':
            30,
            'employee_id':
            self.employee_manager.id
        })
        self.assertEqual(so_line_deliver_global_project.invoice_status,
                         'to invoice')
        self.assertEqual(so_line_deliver_task_project.invoice_status,
                         'to invoice')
        self.assertEqual(sale_order.invoice_status, 'to invoice')

        # Context for sale.advance.payment.inv wizard
        self.context = {
            'active_model': 'sale.order',
            'active_ids': [sale_order.id],
            'active_id': sale_order.id,
            'default_journal_id': self.company_data['default_journal_sale'].id
        }

        # invoice SO
        wizard = self.env['sale.advance.payment.inv'].with_context(
            self.context).create({
                'advance_payment_method':
                'delivered',
                'date_start_invoice_timesheet':
                today - timedelta(days=16),
                'date_end_invoice_timesheet':
                today - timedelta(days=10)
            })

        self.assertTrue(
            wizard.invoicing_timesheet_enabled,
            'The "date_start_invoice_timesheet" and "date_end_invoice_timesheet" field should be visible in the wizard because a product in sale order has service_policy to "Timesheet on Task"'
        )

        with self.assertRaises(UserError):
            wizard.create_invoices()

        self.assertFalse(
            sale_order.invoice_ids,
            'Normally, no invoice will be created because the timesheet logged is after the period defined in date_start_invoice_timesheet and date_end_invoice_timesheet field'
        )

        wizard.write({
            'date_start_invoice_timesheet': today - timedelta(days=10),
            'date_end_invoice_timesheet': today - timedelta(days=6)
        })
        wizard.create_invoices()

        self.assertTrue(
            sale_order.invoice_ids,
            'One invoice should be created because the timesheet logged is between the period defined in wizard'
        )

        invoice = sale_order.invoice_ids[0]
        self.assertEqual(so_line_deliver_global_project.qty_invoiced,
                         timesheet1.unit_amount)

        # validate invoice
        invoice.action_post()

        wizard.write({
            'date_start_invoice_timesheet': today - timedelta(days=16),
            'date_end_invoice_timesheet': today - timedelta(days=4)
        })
        wizard.create_invoices()

        self.assertEqual(len(sale_order.invoice_ids), 2)
        invoice2 = sale_order.invoice_ids[-1]

        self.assertEqual(
            so_line_deliver_global_project.qty_invoiced,
            timesheet1.unit_amount + timesheet3.unit_amount,
            "The last invoice done should have the quantity of the timesheet 3, because the date this timesheet is the only one before the 'date_end_invoice_timesheet' field in the wizard."
        )

        wizard.write({
            'date_start_invoice_timesheet': today - timedelta(days=4),
            'date_end_invoice_timesheet': today
        })

        wizard.create_invoices()

        self.assertEqual(len(sale_order.invoice_ids), 3)
        invoice3 = sale_order.invoice_ids[-1]

        # Check if all timesheets have been invoiced
        self.assertEqual(
            so_line_deliver_global_project.qty_invoiced,
            timesheet1.unit_amount + timesheet2.unit_amount +
            timesheet3.unit_amount)
        self.assertTrue(so_line_deliver_task_project.invoice_lines)
        self.assertEqual(so_line_deliver_task_project.qty_invoiced,
                         timesheet4.unit_amount)
예제 #18
0
    def test_program_rules_one_date(self):
        # Test case: Based on the validity dates and the number of allowed uses

        # VFE NOTE the .rule_id is necessary to ensure the dates constraints doesn't raise
        # because the orm applies the related inverse one by one, raising the constraint...
        self.immediate_promotion_program.rule_id.write({
            'rule_date_from':
            False,
            'rule_date_to':
            Date.to_string((datetime.now() - timedelta(days=2))),
        })

        order = self.empty_order
        order.write({
            'order_line': [(0, False, {
                'product_id': self.product_A.id,
                'name': '1 Product A',
                'product_uom': self.uom_unit.id,
                'product_uom_qty': 1.0,
            }),
                           (0, False, {
                               'product_id': self.product_B.id,
                               'name': '2 Product B',
                               'product_uom': self.uom_unit.id,
                               'product_uom_qty': 1.0,
                           })]
        })
        order.recompute_coupon_lines()
        self.assertNotIn(self.immediate_promotion_program,
                         order._get_applicable_programs())
        self.assertEqual(
            len(order.order_line.ids), 2,
            "The promo offert shouldn't have been applied we're not between the validity dates"
        )

        self.immediate_promotion_program.rule_id.write({
            'rule_date_from':
            Date.to_string((datetime.now() + timedelta(days=1))),
            'rule_date_to':
            False,
        })
        order.recompute_coupon_lines()
        self.assertNotIn(self.immediate_promotion_program,
                         order._get_applicable_programs())
        self.assertEqual(
            len(order.order_line.ids), 2,
            "The promo offert shouldn't have been applied we're not between the validity dates"
        )

        self.immediate_promotion_program.rule_id.write({
            'rule_date_from':
            False,
            'rule_date_to':
            Date.to_string((datetime.now() + timedelta(days=2))),
        })
        order.recompute_coupon_lines()
        self.assertIn(self.immediate_promotion_program,
                      order._get_applicable_programs())
        self.assertEqual(
            len(order.order_line.ids), 3,
            "The promo offer should have been applied as we're between the validity dates"
        )

        self.immediate_promotion_program.rule_id.write({
            'rule_date_from':
            Date.to_string((datetime.now() - timedelta(days=1))),
            'rule_date_to':
            False,
        })
        order.recompute_coupon_lines()
        self.assertIn(self.immediate_promotion_program,
                      order._get_applicable_programs())
        self.assertEqual(
            len(order.order_line.ids), 3,
            "The promo offer should have been applied as we're between the validity dates"
        )
예제 #19
0
    def _check_pos_hash_integrity(self):
        """Checks that all posted or invoiced pos orders have still the same data as when they were posted
        and raises an error with the result.
        """
        def build_order_info(order):
            entry_reference = _('(Receipt ref.: %s)')
            order_reference_string = order.pos_reference and entry_reference % order.pos_reference or ''
            return [
                ctx_tz(order, 'date_order'), order.l10n_fr_hash, order.name,
                order_reference_string,
                ctx_tz(order, 'write_date')
            ]

        hash_verified = True
        msg_alert = ''
        report_dict = {}
        if self._is_accounting_unalterable():
            orders = self.env['pos.order'].search(
                [('state', 'in', ['paid', 'done', 'invoiced']),
                 ('company_id', '=', self.id),
                 ('l10n_fr_secure_sequence_number', '!=', 0)],
                order="l10n_fr_secure_sequence_number ASC")

            if not orders:
                msg_alert = (_(
                    'There isn\'t any order flagged for data inalterability yet for the company %s. This mechanism only runs for point of sale orders generated after the installation of the module France - Certification CGI 286 I-3 bis. - POS',
                    self.env.company.name))
                hash_verified = False

            previous_hash = u''
            start_order_info = []
            for order in orders:
                if order.l10n_fr_hash != order._compute_hash(
                        previous_hash=previous_hash):
                    msg_alert = (_(
                        'Corrupted data on point of sale order with id %s.',
                        order.id))
                    hash_verified = False
                    break
                previous_hash = order.l10n_fr_hash

            if hash_verified:
                orders_sorted_date = orders.sorted(lambda o: o.date_order)
                start_order_info = build_order_info(orders_sorted_date[0])
                end_order_info = build_order_info(orders_sorted_date[-1])

                report_dict.update({
                    'first_order_name': start_order_info[2],
                    'first_order_hash': start_order_info[1],
                    'first_order_date': start_order_info[0],
                    'last_order_name': end_order_info[2],
                    'last_order_hash': end_order_info[1],
                    'last_order_date': end_order_info[0],
                })
            return {
                'result':
                hash_verified and report_dict or 'None',
                'msg_alert':
                msg_alert or 'None',
                'printing_date':
                format_date(self.env, Date.to_string(Date.today())),
            }