예제 #1
0
        def format_numbers(number):
            #format number to str with between 2 and 8 decimals (event if it's .00)
            number_splited = str(number).split('.')
            if len(number_splited) == 1:
                return "%.02f" % number

            cents = number_splited[1]
            if len(cents) > 8:
                return "%.08f" % number
            return float_repr(number, max(2, len(cents)))
예제 #2
0
파일: main.py 프로젝트: EdyKend/odoo
    def infos(self, user_id=None):
        user = request.env['res.users'].browse(user_id) if user_id else request.env.user

        infos = self._make_infos(user, order=False)

        lines = self._get_current_lines(user.id)
        if lines:
            lines = [{'id': line.id,
                      'product': (line.product_id.id, line.product_id.name, float_repr(float_round(line.product_id.price, 2), 2)),
                      'toppings': [(topping.name, float_repr(float_round(topping.price, 2), 2))
                                   for topping in line.topping_ids_1 | line.topping_ids_2 | line.topping_ids_3],
                      'quantity': line.quantity,
                      'price': line.price,
                      'state': line.state, # Only used for _get_state
                      'note': line.note} for line in lines]
            raw_state, state = self._get_state(lines)
            infos.update({
                'total': float_repr(float_round(sum(line['price'] for line in lines), 2), 2),
                'raw_state': raw_state,
                'state': state,
                'lines': lines,
            })
        return infos
예제 #3
0
파일: main.py 프로젝트: ovnicraft/odoo
 def update_eshop_carrier(self, **post):
     order = request.website.sale_get_order()
     carrier_id = int(post['carrier_id'])
     currency = order.currency_id
     if order:
         order._check_carrier_quotation(force_carrier_id=carrier_id)
         return {'status': order.delivery_rating_success,
                 'error_message': order.delivery_message,
                 'carrier_id': carrier_id,
                 'new_amount_delivery': float_repr(currency.round(order.delivery_price), currency.decimal_places),
                 'new_amount_untaxed': order.amount_untaxed,
                 'new_amount_tax': order.amount_tax,
                 'new_amount_total': order.amount_total,
         }
예제 #4
0
    def _get_statement_line_reconciliation_proposition(self, st_line, excluded_ids=None):
        """ Returns move lines that constitute the best guess to reconcile a statement line
            Note: it only looks for move lines in the same currency as the statement line.
        """
        Account_move_line = self.env['account.move.line']

        if not excluded_ids:
            excluded_ids = []
        amount = st_line.amount_currency or st_line.amount
        company_currency = st_line.journal_id.company_id.currency_id
        st_line_currency = st_line.currency_id or st_line.journal_id.currency_id
        currency = (st_line_currency and st_line_currency != company_currency) and st_line_currency.id or False
        precision = st_line_currency and st_line_currency.decimal_places or company_currency.decimal_places
        params = {'company_id': st_line.company_id.id,
                    'account_payable_receivable': (st_line.journal_id.default_credit_account_id.id, st_line.journal_id.default_debit_account_id.id),
                    'amount': float_repr(float_round(amount, precision_digits=precision), precision_digits=precision),
                    'partner_id': st_line.partner_id.id,
                    'excluded_ids': tuple(excluded_ids),
                    'ref': st_line.name,
                    }
        # Look for structured communication match
        if st_line.name:
            add_to_select = ", CASE WHEN aml.ref = %(ref)s THEN 1 ELSE 2 END as temp_field_order "
            add_to_from = " JOIN account_move m ON m.id = aml.move_id "
            select_clause, from_clause, where_clause = st_line._get_common_sql_query(overlook_partner=True, excluded_ids=excluded_ids, split=True)
            sql_query = select_clause + add_to_select + from_clause + add_to_from + where_clause
            sql_query += " AND (aml.ref= %(ref)s or m.name = %(ref)s) \
                    ORDER BY temp_field_order, date_maturity desc, aml.id desc"
            self.env.cr.execute(sql_query, params)
            results = self.env.cr.fetchone()
            if results:
                return Account_move_line.browse(results[0])

        # Look for a single move line with the same amount
        field = currency and 'amount_residual_currency' or 'amount_residual'
        liquidity_field = currency and 'amount_currency' or amount > 0 and 'debit' or 'credit'
        liquidity_amt_clause = currency and '%(amount)s::numeric' or 'abs(%(amount)s::numeric)'
        sql_query = st_line._get_common_sql_query(excluded_ids=excluded_ids) + \
                " AND (" + field + " = %(amount)s::numeric OR (acc.internal_type = 'liquidity' AND " + liquidity_field + " = " + liquidity_amt_clause + ")) \
                ORDER BY date_maturity desc, aml.id desc LIMIT 1"
        self.env.cr.execute(sql_query, params)
        results = self.env.cr.fetchone()
        if results:
            return Account_move_line.browse(results[0])

        return Account_move_line
예제 #5
0
    def check_monetary(self, record, amount, currency, msg=None):
        # determine the possible roundings of amount
        if currency:
            ramount = currency.round(amount)
            samount = float(float_repr(ramount, currency.decimal_places))
        else:
            ramount = samount = amount

        # check the currency on record
        self.assertEqual(record.currency_id, currency)

        # check the value on the record
        self.assertIn(record.amount, [ramount, samount], msg)

        # check the value in the database
        self.cr.execute('SELECT amount FROM test_new_api_mixed WHERE id=%s', [record.id])
        value = self.cr.fetchone()[0]
        self.assertEqual(value, samount, msg)
예제 #6
0
 def format_monetary(number, currency):
     # Format the monetary values to avoid trailing decimals (e.g. 90.85000000000001).
     return float_repr(number, currency.decimal_places)
예제 #7
0
 def try_round(amount, expected, precision_rounding=None):
     value = float_round(amount, precision_rounding=precision_rounding)
     result = float_repr(value, precision_digits=2)
     self.assertEqual(result, expected, 'Rounding error: got %s, expected %s' % (result, expected))
예제 #8
0
 def _get_CtrlSum(self, payments):
     return float_repr(
         float_round(sum(payment['amount'] for payment in payments), 2), 2)
예제 #9
0
    def test_revenue_multi_currency(self):
        """ Create a SO with 2 lines : one for a delivered service, one for a ordered service. Confirm
            and invoice it. For this, we use a partner having a DIFFERENT currency from the current company.
            4 timesheets are logged before invoicing : 2 for delivered, 2 for ordered.
        """
        # create SO and confirm it
        sale_order = self.env['sale.order'].create({
            'partner_id': self.partner_usd.id,
            'partner_invoice_id': self.partner_eur.id,
            'partner_shipping_id': self.partner_eur.id,
            'pricelist_id': self.pricelist_eur.id,
        })
        sale_order_line_delivered = self.env['sale.order.line'].create({
            'name': self.product_deliver.name,
            'product_id': self.product_deliver.id,
            'product_uom_qty': 12,
            'product_uom': self.product_deliver.uom_id.id,
            'price_unit': self.product_deliver.list_price,
            'order_id': sale_order.id,
        })
        sale_order_line_ordered = self.env['sale.order.line'].create({
            'name': self.product_order.name,
            'product_id': self.product_order.id,
            'product_uom_qty': 7,
            'product_uom': self.product_order.uom_id.id,
            'price_unit': self.product_order.list_price,
            'order_id': sale_order.id,
        })
        sale_order_line_ordered.product_id_change()
        sale_order_line_delivered.product_id_change()
        sale_order.action_confirm()

        # log timesheet on tasks
        task_delivered = self.env['project.task'].search([('sale_line_id', '=', sale_order_line_delivered.id)])
        task_ordered = self.env['project.task'].search([('sale_line_id', '=', sale_order_line_ordered.id)])

        timesheet1 = self.env['account.analytic.line'].create({
            'name': 'ts 1',
            'unit_amount': 5,
            'task_id': task_delivered.id,
            'project_id': task_delivered.project_id.id,
        })
        timesheet2 = self.env['account.analytic.line'].create({
            'name': 'ts 2',
            'unit_amount': 2,
            'task_id': task_delivered.id,
            'project_id': task_delivered.project_id.id,
        })
        timesheet3 = self.env['account.analytic.line'].create({
            'name': 'ts 3',
            'unit_amount': 3,
            'task_id': task_ordered.id,
            'project_id': task_ordered.project_id.id,
        })
        timesheet4 = self.env['account.analytic.line'].create({
            'name': 'ts 4',
            'unit_amount': 6,
            'task_id': task_ordered.id,
            'project_id': task_ordered.project_id.id,
        })

        # check theorical revenue
        # Note: conversion from EUR to USD is  *1.2833309567944147
        self.assertEquals(timesheet1.timesheet_invoice_type, 'billable_time', "Billable type on task from delivered service should be 'billabe time'")
        self.assertEquals(timesheet2.timesheet_invoice_type, 'billable_time', "Billable type on task from delivered service should be 'billabe time'")
        self.assertEquals(timesheet3.timesheet_invoice_type, 'billable_fixed', "Billable type on task from ordered service should be 'billabe fixed'")
        self.assertEquals(timesheet4.timesheet_invoice_type, 'billable_fixed', "Billable type on task from ordered service should be 'billabe fixed'")
        self.assertEquals(timesheet1.timesheet_invoice_id, self.env['account.invoice'])
        self.assertEquals(timesheet2.timesheet_invoice_id, self.env['account.invoice'])
        self.assertEquals(timesheet3.timesheet_invoice_id, self.env['account.invoice'])
        # Same computation as the test below, since revenue is stored in company currency
        self.assertEquals(timesheet1.timesheet_revenue, 450, "Revenue computation does not return the correct amount !")
        self.assertEquals(timesheet2.timesheet_revenue, 180, "Revenue computation does not return the correct amount !")
        self.assertEquals(timesheet3.timesheet_revenue, 153, "Revenue computation does not return the correct amount !")
        self.assertEquals(timesheet4.timesheet_revenue, 204, "Revenue computation does not return the correct amount !")

        # invoice the SO
        context = {
            "active_model": 'sale.order',
            "active_ids": [sale_order.id],
            "active_id": sale_order.id,
            'open_invoices': True,
        }
        payment = self.env['sale.advance.payment.inv'].create({
            'advance_payment_method': 'delivered',
        })
        action_invoice = payment.with_context(context).create_invoices()
        invoice_id = action_invoice['res_id']
        invoice = self.env['account.invoice'].browse(invoice_id)

        # update invoice line by setting a reduction, then validate it
        for invoice_line in invoice.invoice_line_ids:
            invoice_line.write({'price_unit': invoice_line.price_unit - 10})
        invoice.action_invoice_open()

        # check concrete revenue
        self.assertEquals(float_repr(timesheet1.timesheet_revenue, precision_digits=2), '385.85', "Revenue computation on invoice validation does not return the correct revenue !")
        self.assertEquals(float_repr(timesheet2.timesheet_revenue, precision_digits=2), '154.35', "Revenue computation on invoice validation does not return the correct revenue !")
        self.assertEquals(float_repr(timesheet3.timesheet_revenue, precision_digits=2), '114.50', "Revenue computation on invoice validation does not return the correct revenue !")
        self.assertEquals(float_repr(timesheet4.timesheet_revenue, precision_digits=2), '152.68', "Revenue computation on invoice validation does not return the correct revenue !")

        # check the invoice is well set
        self.assertEquals(timesheet1.timesheet_invoice_id, invoice)
        self.assertEquals(timesheet2.timesheet_invoice_id, invoice)
        self.assertEquals(timesheet3.timesheet_invoice_id, invoice)
예제 #10
0
 def try_round(amount, expected, digits=3, method='HALF-UP'):
     value = float_round(amount, precision_digits=digits, rounding_method=method)
     result = float_repr(value, precision_digits=digits)
     self.assertEqual(result, expected, 'Rounding error: got %s, expected %s' % (result, expected))
예제 #11
0
 def _get_formatted_amount(self, amount):
     """paypal API is expecting at most two (2) decimal places with a
     period separator."""
     if amount is None:
         return 0
     return float_repr(float_round(amount, 2), 2)
예제 #12
0
 def convert_lines(self, data, model=False, model_id=0, parent_id=None, level=1):
     res = []
     company = self._context.get('company_id') and self.env['res.company'].browse(self._context.get('company_id')[0]) or self.env.user.company_id
     if model and model_id:
         for d in data:
             for m in d['move_lines']:
                 r = {'id': autoIncrement(),
                      'model': model,
                      'model_id': model_id,
                      'unfoldable': False,
                      'parent_id': parent_id,
                      'level': level,
                      'type': 'line',
                      'res_model': 'account.move.line',
                      'res_id': m['lid'],
                      'reference': m['move_name'],
                      'columns': [m['move_name'],
                                  m['ldate'],
                                  m['lcode'],
                                  m['partner_name'],
                                  "%s%s" % (m['lname'], m.get('lref') and " - %s" % m['lref'] or ''),
                                  m['debit'],
                                  m['credit'],
                                  m['balance'],
                                  m['amount_currency'] and "%s %s"%(m['currency_code'],float_repr(m['amount_currency'],company.currency_id.decimal_places)) or company.currency_id.symbol,
                                  ]
                      }
                 res.append(r)
     else:
         total = [(_('Undistributed profit'),"white-space: nowrap;text-align: right;font-weight: normal;font-style: italic;"),0.0,0.0,0.0,company.currency_id.symbol or '']
         for d in data:
             r = {'id': autoIncrement(),
                  'model': model or 'account.account',
                  'model_id': model_id or d.get('account_id'),
                  'unfoldable': False if model else bool(d.get('move_lines')),
                  'parent_id': parent_id,
                  'level': level,
                  'type': 'line',
                  'columns' : ["%s %s"%(d['code'],d['name']),
                               d['debit'],
                               d['credit'],
                               d['balance'],
                               company.currency_id.symbol or '',
                               ]
                  }
             res.append(r)
             total[3] += d['balance']
         if total[3]:
             total[1] = (float_repr(total[3] > 0.0 and total[3] or 0.0, company.currency_id.decimal_places),"white-space: nowrap;text-align: right;font-weight: normal;font-style: italic;")
             total[2] = (float_repr(total[3] < 0.0 and (-1.0 * total[3]) or 0.0, company.currency_id.decimal_places),"white-space: nowrap;text-align: right;font-weight: normal;font-style: italic;")
             total[3] = (float_repr(total[3], company.currency_id.decimal_places),"white-space: nowrap;text-align: right;font-weight: normal;font-style: italic;")
             res.append({
                 'id': autoIncrement(),
                 'model': model or 'account.account',
                 'model_id': 0,
                 'unfoldable': False,
                 'parent_id': 0,
                 'level': level,
                 'type': 'line',
                 'columns': total,
             })
     return res
예제 #13
0
파일: test_float.py 프로젝트: 10537/odoo
 def try_round(amount, expected, digits=3, method='HALF-UP'):
     value = float_round(amount, precision_digits=digits, rounding_method=method)
     result = float_repr(value, precision_digits=digits)
     self.assertEqual(result, expected, 'Rounding error: got %s, expected %s' % (result, expected))
예제 #14
0
 def format_monetary(number, currency):
     # Format the monetary values to avoid trailing decimals
     # (e.g. 90.85000000000001).
     return float_repr(abs(number), 2)
예제 #15
0
 def format_monetary(amount):
     # Format the monetary values to avoid trailing decimals (e.g. 90.85000000000001).
     return float_repr(amount, self.currency_id.decimal_places)
예제 #16
0
    def _get_statement_line_reconciliation_proposition(self,
                                                       st_line,
                                                       excluded_ids=None):
        """ Returns move lines that constitute the best guess to reconcile a statement line
            Note: it only looks for move lines in the same currency as the statement line.
        """
        Account_move_line = self.env['account.move.line']

        if not excluded_ids:
            excluded_ids = []
        amount = st_line.amount_currency or st_line.amount
        company_currency = st_line.journal_id.company_id.currency_id
        st_line_currency = st_line.currency_id or st_line.journal_id.currency_id
        currency = (st_line_currency and st_line_currency != company_currency
                    ) and st_line_currency.id or False
        precision = st_line_currency and st_line_currency.decimal_places or company_currency.decimal_places
        params = {
            'company_id':
            self.env.user.company_id.id,
            'account_payable_receivable':
            (st_line.journal_id.default_credit_account_id.id,
             st_line.journal_id.default_debit_account_id.id),
            'amount':
            float_repr(float_round(amount, precision_digits=precision),
                       precision_digits=precision),
            'partner_id':
            st_line.partner_id.id,
            'excluded_ids':
            tuple(excluded_ids),
            'ref':
            st_line.name,
        }
        # Look for structured communication match
        if st_line.name:
            add_to_select = ", CASE WHEN aml.ref = %(ref)s THEN 1 ELSE 2 END as temp_field_order "
            add_to_from = " JOIN account_move m ON m.id = aml.move_id "
            select_clause, from_clause, where_clause = st_line._get_common_sql_query(
                overlook_partner=True, excluded_ids=excluded_ids, split=True)
            sql_query = select_clause + add_to_select + from_clause + add_to_from + where_clause
            sql_query += " AND (aml.ref= %(ref)s or m.name = %(ref)s) \
                    ORDER BY temp_field_order, date_maturity desc, aml.id desc"

            self.env.cr.execute(sql_query, params)
            results = self.env.cr.fetchone()
            if results:
                return Account_move_line.browse(results[0])

        # Look for a single move line with the same amount
        field = currency and 'amount_residual_currency' or 'amount_residual'
        liquidity_field = currency and 'amount_currency' or amount > 0 and 'debit' or 'credit'
        liquidity_amt_clause = currency and '%(amount)s::numeric' or 'abs(%(amount)s::numeric)'
        sql_query = st_line._get_common_sql_query(excluded_ids=excluded_ids) + \
                " AND ("+field+" = %(amount)s::numeric OR (acc.internal_type = 'liquidity' AND "+liquidity_field+" = " + liquidity_amt_clause + ")) \
                ORDER BY date_maturity desc, aml.id desc LIMIT 1"

        self.env.cr.execute(sql_query, params)
        results = self.env.cr.fetchone()
        if results:
            return Account_move_line.browse(results[0])

        return Account_move_line
예제 #17
0
 def _set_dutiable(self, total_value, currency_name):
     dutiable = self.factory.Dutiable()
     dutiable.DeclaredValue = float_repr(total_value, 2)
     dutiable.DeclaredCurrency = currency_name
     return dutiable
예제 #18
0
    def _create_00_04_00_document(self, doc_payments):
        """
        Crea il Documento di Tipo ISO 00_04_00
        """
        sepa_payment = CBIPaymentRequest()
        company = self.journal_id.company_id
        name_length = self.sct_generic and 35 or 70
        val_MsgId = str(int(time.time() * 100))[-10:]
        val_MsgId = self._sanitize_communication(
            self.journal_id.company_id.name[-15:]) + val_MsgId
        val_MsgId = str(random.random()) + val_MsgId
        val_MsgId = val_MsgId[-30:]

        val_NbOfTxs = str(len(doc_payments))
        if len(val_NbOfTxs) > 15:
            raise ValidationError(
                _("Too many transactions for a single file."))
        if not self.journal_id.bank_account_id.bank_bic:
            raise UserError(
                _("There is no Bank Identifier Code recorded for bank account '%s' of journal '%s'"
                  ) % (self.journal_id.bank_account_id.acc_number,
                       self.journal_id.name))

        #HEADER
        sepa_payment.GrpHdr = CBIGroupHeader(
            MsgId=val_MsgId,
            CreDtTm=time.strftime("%Y-%m-%dT%H:%M:%S"),
            NbOfTxs=val_NbOfTxs,
            CtrlSum=self._get_CtrlSum(doc_payments),
        )

        sepa_payment.GrpHdr.InitgPty = CBIPartyIdentification1(
            Nm=self._sanitize_communication(
                company.sepa_initiating_party_name[:name_length]),
            Id=CBIIdType1())
        sepa_payment.GrpHdr.InitgPty.Id.OrgId = CBIOrganisationIdentification1(
        )
        sepa_payment.GrpHdr.InitgPty.Id.OrgId.append(
            CBIGenericIdentification1(Id='0799996F', Issr='CBI'))

        #PAYMENT
        sepa_payment.PmtInf = CBIPaymentInstructionInformation(
            PmtInfId=(val_MsgId + str(self.journal_id.id))[-30:],
            PmtMtd='TRA',
            PmtTpInf=CBIPaymentTypeInformation1(),
            ReqdExctnDt=fields.Date.to_string(self.date),
            Dbtr=CBIPartyIdentification4(),
            DbtrAcct=CBICashAccount1(),
            DbtrAgt=CBIBranchAndFinancialInstitutionIdentification2(),
            ChrgBr='SLEV',
            CdtTrfTxInf=[])

        sepa_payment.PmtInf.Dbtr = CBIPartyIdentification4(
            Nm=self._sanitize_communication(
                company.sepa_initiating_party_name[:name_length]),
            PstlAdr=CBIPostalAddress6(
                Ctry=company.partner_id.country_id.code, ),
        )

        sepa_payment.PmtInf.DbtrAcct.Id = CBIAccountIdentification1(
            IBAN=self.journal_id.bank_account_id.sanitized_acc_number)

        sepa_payment.PmtInf.DbtrAgt = CBIBranchAndFinancialInstitutionIdentification2(
            FinInstnId=CBIFinancialInstitutionIdentification3(
                ClrSysMmbId=CBIClearingSystemMemberIdentification1(
                    MmbId='02008')))

        for payment in doc_payments:
            sepa_payment.PmtInf.CdtTrfTxInf.append(
                CBICreditTransferTransactionInformation(
                    PmtId=PaymentIdentification1(
                        InstrId=self._sanitize_communication(payment.name),
                        EndToEndId=(
                            (val_MsgId + str(self.journal_id.id))[-30:] +
                            str(payment.id))[-30:]),
                    Amt=CBIAmountType1(
                        InstdAmt=ActiveOrHistoricCurrencyAndAmount(
                            float_repr(float_round(payment.amount, 2), 2),
                            Ccy=payment.currency_id
                            and payment.currency_id.name
                            or payment.journal_id.company_id.currency_id.name,
                        )),
                    Cdtr=CBIPartyIdentification3(
                        Nm=self._sanitize_communication(
                            (payment.partner_bank_account_id.acc_holder_name
                             or payment.partner_id.name)[:70]),
                        PstlAdr=CBIPostalAddress6(
                            Ctry=payment.partner_id.country_id.code, ),
                        CtryOfRes=payment.partner_id.country_id.code),
                    CdtrAcct=CBICashAccount2(Id=CBIAccountIdentification1(
                        IBAN=self._sanitize_communication(
                            payment.partner_bank_account_id.acc_number.replace(
                                ' ', '')))),
                    RmtInf=RemittanceInformation5(Ustrd=[
                        self._sanitize_communication(str(
                            payment.communication))
                    ])))

        attach_str = sepa_payment.toxml(encoding="UTF-8", )

        return attach_str
예제 #19
0
파일: test_float.py 프로젝트: 10537/odoo
 def try_round(amount, expected):
     digits = max(0, -int(log10(currency.rounding)))
     result = float_repr(currency.round(amount), precision_digits=digits)
     self.assertEqual(result, expected, 'Rounding error: got %s, expected %s' % (result, expected))
예제 #20
0
 def format_monetary(number, decimal_places=2):
     # Facturx requires the monetary values to be rounded to 2 decimal values
     return float_repr(number, decimal_places)
예제 #21
0
 def format_monetary(number, currency):
     # Format the monetary values to avoid trailing decimals (e.g. 90.85000000000001).
     return float_repr(number, currency.decimal_places)
예제 #22
0
 def try_round(amount, expected, precision_rounding=None):
     value = float_round(amount, precision_rounding=precision_rounding)
     result = float_repr(value, precision_digits=2)
     self.assertEqual(result, expected, 'Rounding error: got %s, expected %s' % (result, expected))
예제 #23
0
    def test_revenue_multi_currency(self):
        """ Create a SO with 2 lines : one for a delivered service, one for a ordered service. Confirm
            and invoice it. For this, we use a partner having a DIFFERENT currency from the current company.
            4 timesheets are logged before invoicing : 2 for delivered, 2 for ordered.
        """
        # create SO and confirm it
        sale_order = self.env['sale.order'].create({
            'partner_id': self.partner_usd.id,
            'partner_invoice_id': self.partner_eur.id,
            'partner_shipping_id': self.partner_eur.id,
            'pricelist_id': self.pricelist_eur.id,
        })
        sale_order_line_delivered = self.env['sale.order.line'].create({
            'name': self.product_deliver.name,
            'product_id': self.product_deliver.id,
            'product_uom_qty': 12,
            'product_uom': self.product_deliver.uom_id.id,
            'price_unit': self.product_deliver.list_price,
            'order_id': sale_order.id,
        })
        sale_order_line_ordered = self.env['sale.order.line'].create({
            'name': self.product_order.name,
            'product_id': self.product_order.id,
            'product_uom_qty': 7,
            'product_uom': self.product_order.uom_id.id,
            'price_unit': self.product_order.list_price,
            'order_id': sale_order.id,
        })
        sale_order_line_ordered.product_id_change()
        sale_order_line_delivered.product_id_change()
        sale_order.action_confirm()

        # log timesheet on tasks
        task_delivered = self.env['project.task'].search([('sale_line_id', '=', sale_order_line_delivered.id)])
        task_ordered = self.env['project.task'].search([('sale_line_id', '=', sale_order_line_ordered.id)])

        timesheet1 = self.env['account.analytic.line'].create({
            'name': 'ts 1',
            'unit_amount': 5,
            'task_id': task_delivered.id,
            'project_id': task_delivered.project_id.id,
        })
        timesheet2 = self.env['account.analytic.line'].create({
            'name': 'ts 2',
            'unit_amount': 2,
            'task_id': task_delivered.id,
            'project_id': task_delivered.project_id.id,
        })
        timesheet3 = self.env['account.analytic.line'].create({
            'name': 'ts 3',
            'unit_amount': 3,
            'task_id': task_ordered.id,
            'project_id': task_ordered.project_id.id,
        })
        timesheet4 = self.env['account.analytic.line'].create({
            'name': 'ts 4',
            'unit_amount': 6,
            'task_id': task_ordered.id,
            'project_id': task_ordered.project_id.id,
        })

        # check theorical revenue
        # Note: conversion from EUR to USD is  *1.2833309567944147
        self.assertEquals(timesheet1.timesheet_invoice_type, 'billable_time', "Billable type on task from delivered service should be 'billabe time'")
        self.assertEquals(timesheet2.timesheet_invoice_type, 'billable_time', "Billable type on task from delivered service should be 'billabe time'")
        self.assertEquals(timesheet3.timesheet_invoice_type, 'billable_fixed', "Billable type on task from ordered service should be 'billabe fixed'")
        self.assertEquals(timesheet4.timesheet_invoice_type, 'billable_fixed', "Billable type on task from ordered service should be 'billabe fixed'")
        self.assertEquals(timesheet1.timesheet_invoice_id, self.env['account.invoice'])
        self.assertEquals(timesheet2.timesheet_invoice_id, self.env['account.invoice'])
        self.assertEquals(timesheet3.timesheet_invoice_id, self.env['account.invoice'])
        # Same computation as the test below, since revenue is stored in company currency
        self.assertEquals(timesheet1.timesheet_revenue, 450, "Revenue computation does not return the correct amount !")
        self.assertEquals(timesheet2.timesheet_revenue, 180, "Revenue computation does not return the correct amount !")
        self.assertEquals(timesheet3.timesheet_revenue, 153, "Revenue computation does not return the correct amount !")
        self.assertEquals(timesheet4.timesheet_revenue, 204, "Revenue computation does not return the correct amount !")

        # invoice the SO
        context = {
            "active_model": 'sale.order',
            "active_ids": [sale_order.id],
            "active_id": sale_order.id,
            'open_invoices': True,
        }
        payment = self.env['sale.advance.payment.inv'].create({
            'advance_payment_method': 'delivered',
        })
        action_invoice = payment.with_context(context).create_invoices()
        invoice_id = action_invoice['res_id']
        invoice = self.env['account.invoice'].browse(invoice_id)

        # update invoice line by setting a reduction, then validate it
        for invoice_line in invoice.invoice_line_ids:
            invoice_line.write({'price_unit': invoice_line.price_unit - 10})
        invoice.action_invoice_open()

        # check concrete revenue
        self.assertEquals(float_repr(timesheet1.timesheet_revenue, precision_digits=2), '385.85', "Revenue computation on invoice validation does not return the correct revenue !")
        self.assertEquals(float_repr(timesheet2.timesheet_revenue, precision_digits=2), '154.35', "Revenue computation on invoice validation does not return the correct revenue !")
        self.assertEquals(float_repr(timesheet3.timesheet_revenue, precision_digits=2), '114.50', "Revenue computation on invoice validation does not return the correct revenue !")
        self.assertEquals(float_repr(timesheet4.timesheet_revenue, precision_digits=2), '152.68', "Revenue computation on invoice validation does not return the correct revenue !")

        # check the invoice is well set
        self.assertEquals(timesheet1.timesheet_invoice_id, invoice)
        self.assertEquals(timesheet2.timesheet_invoice_id, invoice)
        self.assertEquals(timesheet3.timesheet_invoice_id, invoice)
예제 #24
0
 def try_round(amount, expected):
     digits = max(0, -int(log10(currency.rounding)))
     result = float_repr(currency.round(amount), precision_digits=digits)
     self.assertEqual(result, expected, 'Rounding error: got %s, expected %s' % (result, expected))