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)))
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
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, }
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
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)
def format_monetary(number, currency): # Format the monetary values to avoid trailing decimals (e.g. 90.85000000000001). return float_repr(number, currency.decimal_places)
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))
def _get_CtrlSum(self, payments): return float_repr( float_round(sum(payment['amount'] for payment in payments), 2), 2)
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)
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))
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)
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
def format_monetary(number, currency): # Format the monetary values to avoid trailing decimals # (e.g. 90.85000000000001). return float_repr(abs(number), 2)
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)
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
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
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
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))
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)