[REF] account,sale*: remove local cache for currency rates

Since it is cached by the ORM (see parent commit), there is no need to
manage the caching in the business code anymore.
In most cases in addition to making the code shorter, it also makes it
more readable by making the direction of the rate more obvious with the
use of the `to_currency` parameter.

closes odoo/odoo#137609

Signed-off-by: Raphael Collet <rco@odoo.com>
This commit is contained in:
william-andre
2023-10-25 15:50:33 +00:00
parent 9353a6f9ba
commit d8627c4e38
12 changed files with 55 additions and 149 deletions
@@ -458,14 +458,13 @@ class account_journal(models.Model):
)
}
curr_cache = {}
sale_purchase_journals._fill_dashboard_data_count(dashboard_data, 'account.move', 'entries_count', [])
for journal in sale_purchase_journals:
# User may have read access on the journal but not on the company
currency = journal.currency_id or self.env['res.currency'].browse(journal.company_id.sudo().currency_id.id)
(number_waiting, sum_waiting) = self._count_results_and_sum_amounts(query_results_to_pay[journal.id], currency, curr_cache=curr_cache)
(number_draft, sum_draft) = self._count_results_and_sum_amounts(query_results_drafts[journal.id], currency, curr_cache=curr_cache)
(number_late, sum_late) = self._count_results_and_sum_amounts(late_query_results[journal.id], currency, curr_cache=curr_cache)
(number_waiting, sum_waiting) = self._count_results_and_sum_amounts(query_results_to_pay[journal.id], currency)
(number_draft, sum_draft) = self._count_results_and_sum_amounts(query_results_drafts[journal.id], currency)
(number_late, sum_late) = self._count_results_and_sum_amounts(late_query_results[journal.id], currency)
amount_total_signed_sum, count = to_check_vals.get(journal.id, (0, 0))
dashboard_data[journal.id].update({
'number_to_check': count,
@@ -530,7 +529,7 @@ class account_journal(models.Model):
('move_type', 'in', self.env['account.move'].get_invoice_types(include_receipts=True)),
])
def _count_results_and_sum_amounts(self, results_dict, target_currency, curr_cache=None):
def _count_results_and_sum_amounts(self, results_dict, target_currency):
""" Loops on a query result to count the total number of invoices and sum
their amount_total field (expressed in the given target currency).
amount_total must be signed!
@@ -538,22 +537,16 @@ class account_journal(models.Model):
# Create a cache with currency rates to avoid unnecessary SQL requests. Do not copy
# curr_cache on purpose, so the dictionary is modified and can be re-used for subsequent
# calls of the method.
curr_cache = {} if curr_cache is None else curr_cache
total_amount = 0
for result in results_dict:
document_currency = self.env['res.currency'].browse(result.get('currency'))
company = self.env['res.company'].browse(result.get('company_id')) or self.env.company
date = result.get('invoice_date') or fields.Date.context_today(self)
if document_currency == target_currency:
total_amount += result.get('amount_total') or 0
elif company.currency_id == target_currency:
if company.currency_id == target_currency:
total_amount += result.get('amount_total_company') or 0
else:
key = (document_currency, target_currency, company, date)
if key not in curr_cache:
curr_cache[key] = self.env['res.currency']._get_conversion_rate(*key)
total_amount += (result.get('amount_total') or 0) * curr_cache[key]
total_amount += document_currency._convert(result.get('amount_total'), target_currency, company, date)
return (len(results_dict), target_currency.round(total_amount))
def _get_journal_dashboard_bank_running_balance(self):
@@ -617,11 +610,10 @@ class account_journal(models.Model):
""", [self.ids])
query_result = group_by_journal(self.env.cr.dictfetchall())
result = {}
curr_cache = {}
for journal in self:
# User may have read access on the journal but not on the company
currency = journal.currency_id or self.env['res.currency'].browse(journal.company_id.sudo().currency_id.id)
result[journal.id] = self._count_results_and_sum_amounts(query_result[journal.id], currency, curr_cache)
result[journal.id] = self._count_results_and_sum_amounts(query_result[journal.id], currency)
return result
def _get_move_action_context(self):
+1 -10
View File
@@ -2,7 +2,6 @@ import ast
from collections import defaultdict
from contextlib import contextmanager
from datetime import date, timedelta
from functools import lru_cache
from odoo import api, fields, models, Command, _
from odoo.exceptions import ValidationError, UserError
@@ -634,17 +633,9 @@ class AccountMoveLine(models.Model):
@api.depends('currency_id', 'company_id', 'move_id.date')
def _compute_currency_rate(self):
@lru_cache()
def get_rate(from_currency, to_currency, company, date):
return self.env['res.currency']._get_conversion_rate(
from_currency=from_currency,
to_currency=to_currency,
company=company,
date=date,
)
for line in self:
if line.currency_id:
line.currency_rate = get_rate(
line.currency_rate = self.env['res.currency']._get_conversion_rate(
from_currency=line.company_currency_id,
to_currency=line.currency_id,
company=line.company_id,
@@ -683,13 +683,6 @@ class AccountPaymentRegister(models.TransientModel):
'write_off_line_vals': [],
}
conversion_rate = self.env['res.currency']._get_conversion_rate(
self.currency_id,
self.company_id.currency_id,
self.company_id,
self.payment_date,
)
if self.payment_difference_handling == 'reconcile':
if self.early_payment_discount_mode:
epd_aml_values_list = []
@@ -698,11 +691,11 @@ class AccountPaymentRegister(models.TransientModel):
epd_aml_values_list.append({
'aml': aml,
'amount_currency': -aml.amount_residual_currency,
'balance': aml.company_currency_id.round(-aml.amount_residual_currency * conversion_rate),
'balance': aml.currency_id._convert(-aml.amount_residual_currency, aml.company_currency_id, date=self.payment_date),
})
open_amount_currency = self.payment_difference * (-1 if self.payment_type == 'outbound' else 1)
open_balance = self.company_id.currency_id.round(open_amount_currency * conversion_rate)
open_balance = self.currency_id._convert(open_amount_currency, self.company_id.currency_id, self.company_id, self.payment_date)
early_payment_values = self.env['account.move']._get_invoice_counterpart_amls_for_early_payment_discount(epd_aml_values_list, open_balance)
for aml_values_list in early_payment_values.values():
payment_vals['write_off_line_vals'] += aml_values_list
@@ -715,14 +708,13 @@ class AccountPaymentRegister(models.TransientModel):
# Send money.
write_off_amount_currency = -self.payment_difference
write_off_balance = self.company_id.currency_id.round(write_off_amount_currency * conversion_rate)
payment_vals['write_off_line_vals'].append({
'name': self.writeoff_label,
'account_id': self.writeoff_account_id.id,
'partner_id': self.partner_id.id,
'currency_id': self.currency_id.id,
'amount_currency': write_off_amount_currency,
'balance': write_off_balance,
'balance': self.currency_id._convert(write_off_amount_currency, self.company_id.currency_id, self.company_id, self.payment_date),
})
return payment_vals
@@ -760,24 +752,17 @@ class AccountPaymentRegister(models.TransientModel):
if mode == 'early_payment':
payment_vals['amount'] = total_amount
conversion_rate = self.env['res.currency']._get_conversion_rate(
currency,
self.company_id.currency_id,
self.company_id,
self.payment_date,
)
epd_aml_values_list = []
for aml in batch_result['lines']:
if aml.move_id._is_eligible_for_early_payment_discount(currency, self.payment_date):
epd_aml_values_list.append({
'aml': aml,
'amount_currency': -aml.amount_residual_currency,
'balance': aml.company_currency_id.round(-aml.amount_residual_currency * conversion_rate),
'balance': currency._convert(-aml.amount_residual_currency, aml.company_currency_id, self.company_id, self.payment_date),
})
open_amount_currency = (batch_values['source_amount_currency'] - total_amount) * (-1 if batch_values['payment_type'] == 'outbound' else 1)
open_balance = self.company_id.currency_id.round(open_amount_currency * conversion_rate)
open_balance = currency._convert(open_amount_currency, aml.company_currency_id, self.company_id, self.payment_date)
early_payment_values = self.env['account.move']\
._get_invoice_counterpart_amls_for_early_payment_discount(epd_aml_values_list, open_balance)
for aml_values_list in early_payment_values.values():
+2 -4
View File
@@ -155,8 +155,6 @@ class AccruedExpenseRevenue(models.TransientModel):
values = _get_aml_vals(order, self.amount, 0, account.id, label=_('Manual entry'), analytic_distribution=distribution)
move_lines.append(Command.create(values))
else:
other_currency = self.company_id.currency_id != order.currency_id
rate = order.currency_id._get_rates(self.company_id, self.date).get(order.currency_id.id) if other_currency else 1.0
# create a virtual order that will allow to recompute the qty delivered/received (and dependancies)
# without actually writing anything on the real record (field is computed and stored)
o = order.new(origin=order)
@@ -179,14 +177,14 @@ class AccruedExpenseRevenue(models.TransientModel):
for order_line in lines:
if is_purchase:
account = self._get_computed_account(order, order_line.product_id, is_purchase)
amount = self.company_id.currency_id.round(order_line.qty_to_invoice * order_line.price_unit / rate)
amount_currency = order_line.currency_id.round(order_line.qty_to_invoice * order_line.price_unit)
amount = order.currency_id._convert(amount_currency, self.company_id.currency_id, self.company_id)
fnames = ['qty_to_invoice', 'qty_received', 'qty_invoiced', 'invoice_lines']
label = _('%s - %s; %s Billed, %s Received at %s each', order.name, _ellipsis(order_line.name, 20), order_line.qty_invoiced, order_line.qty_received, formatLang(self.env, order_line.price_unit, currency_obj=order.currency_id))
else:
account = self._get_computed_account(order, order_line.product_id, is_purchase)
amount = self.company_id.currency_id.round(order_line.untaxed_amount_to_invoice / rate)
amount_currency = order_line.untaxed_amount_to_invoice
amount = order.currency_id._convert(amount_currency, self.company_id.currency_id, self.company_id)
fnames = ['qty_to_invoice', 'untaxed_amount_to_invoice', 'qty_invoiced', 'qty_delivered', 'invoice_lines']
label = _('%s - %s; %s Invoiced, %s Delivered at %s each', order.name, _ellipsis(order_line.name, 20), order_line.qty_invoiced, order_line.qty_delivered, formatLang(self.env, order_line.price_unit, currency_obj=order.currency_id))
distribution = order_line.analytic_distribution if order_line.analytic_distribution else {}
@@ -4,7 +4,8 @@
import json
from collections import defaultdict
from odoo import models, _lt, fields
from odoo import models, _lt
from odoo.tools.misc import OrderedSet
class Project(models.Model):
@@ -35,13 +36,13 @@ class Project(models.Model):
bills_move_line_read = self._cr.dictfetchall()
if bills_move_line_read:
# Get conversion rate from currencies to currency of the current company
currency_ids = {bml['currency_id'] for bml in bills_move_line_read + [{'currency_id': self.currency_id.id}]}
rates = self.env['res.currency'].browse(list(currency_ids))._get_rates(self.company_id or self.env.company, fields.Date.context_today(self))
conversion_rates = {cid: self.currency_id.rate / rate_from for cid, rate_from in rates.items()}
currency_ids = OrderedSet(bml['currency_id'] for bml in bills_move_line_read)
amount_invoiced = amount_to_invoice = 0.0
move_ids = set()
for moves_read in bills_move_line_read:
price_subtotal = self.currency_id.round(moves_read['price_subtotal'] * conversion_rates[moves_read['currency_id']])
price_subtotal = self.env['res.currency'].browse(moves_read['currency_id']).with_prefetch(currency_ids)._convert(
from_amount=moves_read['price_subtotal'], to_currency=self.currency_id,
)
analytic_contribution = moves_read['analytic_distribution'][str(self.analytic_account_id.id)] / 100.
move_ids.add(moves_read['move_id'])
if moves_read['parent_state'] == 'draft':
@@ -151,16 +152,10 @@ class Project(models.Model):
revenue_ids.append(aal['id'])
total_revenues = total_costs = 0.0
rates_per_currency_id = self.env['res.currency'].browse(set_currency_ids)._get_rates(self.company_id or self.env.company, fields.Date.context_today(self))
project_currency_rate = rates_per_currency_id[self.currency_id.id]
for currency_id, dict_amounts in dict_amount_per_currency_id.items():
if currency_id == self.currency_id.id:
total_revenues += dict_amounts['revenues']
total_costs += dict_amounts['costs']
continue
rate = project_currency_rate / rates_per_currency_id[currency_id]
total_revenues += self.currency_id.round(dict_amounts['revenues'] * rate)
total_costs += self.currency_id.round(dict_amounts['costs'] * rate)
currency = self.env['res.currency'].browse(currency_id).with_prefetch(dict_amount_per_currency_id)
total_revenues += currency._convert(dict_amounts['revenues'], self.currency_id, self.company_id)
total_costs += currency._convert(dict_amounts['costs'], self.currency_id, self.company_id)
# we dont know what part of the numbers has already been billed or not, so we have no choice but to put everything under the billed/invoiced columns.
# The to bill/to invoice ones will simply remain 0
@@ -97,21 +97,15 @@ class Project(models.Model):
return {}
expense_ids = []
amount_billed = 0.0
dict_amount_per_currency = defaultdict(lambda: 0.0)
set_currency_ids = {self.currency_id.id}
all_currencies = {res['currency_id'] for res in expenses_read_group}
for res in expenses_read_group:
if can_see_expense:
expense_ids.extend(res['ids'])
set_currency_ids.add(res['currency_id'])
dict_amount_per_currency[res['currency_id']] += res['untaxed_amount']
rate_per_currency_id = self.env['res.currency'].browse(set_currency_ids)._get_rates(self.company_id or self.env.company, fields.Date.context_today(self))
project_currency_rate = rate_per_currency_id[self.currency_id.id]
for currency_id, amount in dict_amount_per_currency.items():
if currency_id == self.currency_id.id:
amount_billed += amount
continue
rate = project_currency_rate / rate_per_currency_id[currency_id]
amount_billed += self.currency_id.round(amount * rate)
amount_billed += self.env['res.currency'].browse(res['currency_id']).with_prefetch(all_currencies)._convert(
from_amount=res['untaxed_amount'],
to_currency=self.currency_id,
company=self.company_id,
)
section_id = 'expenses'
expense_profitability_items = {
+1 -9
View File
@@ -73,16 +73,8 @@ class Project(models.Model):
if mrp_aal_read_group:
can_see_manufactoring_order = with_action and len(self) == 1 and self.user_has_groups('mrp.group_mrp_user')
total_amount = 0
currency_ids = {currency.id for currency, amount in mrp_aal_read_group}
currency_ids.add(self.currency_id.id)
rate_per_currency_id = self.env['res.currency'].browse(currency_ids)._get_rates(self.company_id or self.env.company, fields.Date.context_today(self))
project_currency_rate = rate_per_currency_id[self.currency_id.id]
for currency, amount_summed in mrp_aal_read_group:
if currency != self.currency_id:
rate = project_currency_rate / rate_per_currency_id[currency.id]
total_amount += self.currency_id.round(amount_summed * rate)
else:
total_amount += amount_summed
total_amount += currency._convert(amount_summed, self.currency_id, self.company_id)
mrp_costs = {
'id': mrp_category,
@@ -5,8 +5,8 @@ import json
from odoo import api, fields, models, _, _lt
from odoo.osv import expression
from odoo.tools.misc import OrderedSet
from datetime import date
class Project(models.Model):
_inherit = "project.project"
@@ -139,17 +139,14 @@ class Project(models.Model):
purchase_order_line_invoice_line_ids = self._get_already_included_profitability_invoice_line_ids()
with_action = with_action and self.user_has_groups('purchase.group_purchase_user, account.group_account_invoice, account.group_account_readonly')
if purchase_order_line_read:
# Get conversion rate from currencies to currency of the current company
convert_company = self.company_id or self.env.company
currency_ids = {pol['currency_id'] for pol in purchase_order_line_read + [{'currency_id': self.currency_id.id}]}
rates = self.env['res.currency'].browse(list(currency_ids))._get_rates(convert_company, date.today())
conversion_rates = {cid: rates[self.currency_id.id] / rate_from for cid, rate_from in rates.items()}
currency_ids = OrderedSet(pol['currency_id'] for pol in purchase_order_line_read)
amount_invoiced = amount_to_invoice = 0.0
purchase_order_line_ids = []
for pol_read in purchase_order_line_read:
purchase_order_line_invoice_line_ids.extend(pol_read['invoice_lines'].ids)
price_unit = self.currency_id.round(pol_read['price_unit'] * conversion_rates[pol_read['currency_id']])
currency = self.env['res.currency'].browse(pol_read['currency_id']).with_prefetch(currency_ids)
price_unit = currency._convert(pol_read['price_unit'], self.currency_id, self.company_id)
analytic_contribution = pol_read['analytic_distribution'][str(self.analytic_account_id.id)] / 100.
amount_invoiced -= price_unit * pol_read['qty_invoiced'] * analytic_contribution if pol_read['qty_invoiced'] > 0 else 0.0
if pol_read['qty_to_invoice'] > 0:
@@ -24,9 +24,6 @@ class Project(models.Model):
return {}
expenses_per_so_id = {}
expense_ids = []
amount_billed = 0.0
today = fields.Date.context_today(self)
convert_company = self.company_id or self.env.company
dict_amount_per_currency = defaultdict(lambda: 0.0)
for res in expenses_read_group:
so_id = res['sale_order_id']
@@ -35,13 +32,11 @@ class Project(models.Model):
if can_see_expense:
expense_ids.extend(res['ids'])
dict_amount_per_currency[res['currency_id']] += res['untaxed_amount_currency']
amount_billed = 0.0
for currency_id in dict_amount_per_currency:
if currency_id == self.currency_id.id:
amount_billed += dict_amount_per_currency[currency_id]
continue
currency = self.env['res.currency'].browse(currency_id)
rate = currency._get_conversion_rate(currency, self.currency_id, convert_company, today)
amount_billed += self.currency_id.round(dict_amount_per_currency[currency_id] * rate)
currency = self.env['res.currency'].browse(currency_id).with_prefetch(dict_amount_per_currency)
amount_billed += currency._convert(dict_amount_per_currency[currency_id], self.currency_id, self.company_id)
sol_read_group = self.env['sale.order.line'].sudo()._read_group(
[
@@ -65,18 +60,9 @@ class Project(models.Model):
dict_invoices_amount_per_currency[currency]['to_invoice'] += untaxed_amount_to_invoice_sum
dict_invoices_amount_per_currency[currency]['invoiced'] += untaxed_amount_invoiced_sum
reinvoice_expense_ids += expense_data_per_product_id[product_id]
rate_per_currency_id = {self.currency_id.id: 1}
if len(set_currency_ids) > 1:
rate_per_currency_id = self.env['res.currency'].browse(set_currency_ids)._get_rates(self.company_id or self.env.company, today)
project_currency_rate = rate_per_currency_id[self.currency_id.id]
for currency, revenues in dict_invoices_amount_per_currency.items():
if currency.id == self.currency_id.id:
total_amount_expense_to_invoice += revenues['to_invoice']
total_amount_expense_invoiced += revenues['invoiced']
continue
rate = project_currency_rate / rate_per_currency_id[currency.id]
total_amount_expense_to_invoice += self.currency_id.round(revenues['to_invoice'] * rate)
total_amount_expense_invoiced += self.currency_id.round(revenues['invoiced'] * rate)
total_amount_expense_to_invoice += currency._convert(revenues['to_invoice'], self.currency_id, self.company_id)
total_amount_expense_invoiced += currency._convert(revenues['invoiced'], self.currency_id, self.company_id)
section_id = 'expenses'
sequence = self._get_profitability_sequence_per_invoice_type()[section_id]
+6 -17
View File
@@ -401,24 +401,13 @@ class SaleOrder(models.Model):
@api.depends('currency_id', 'date_order', 'company_id')
def _compute_currency_rate(self):
cache = {}
for order in self:
order_date = order.date_order.date()
if not order.company_id:
order.currency_rate = order.currency_id.with_context(date=order_date).rate or 1.0
continue
elif not order.currency_id:
order.currency_rate = 1.0
else:
key = (order.company_id.id, order_date, order.currency_id.id)
if key not in cache:
cache[key] = self.env['res.currency']._get_conversion_rate(
from_currency=order.company_id.currency_id,
to_currency=order.currency_id,
company=order.company_id,
date=order_date,
)
order.currency_rate = cache[key]
order.currency_rate = self.env['res.currency']._get_conversion_rate(
from_currency=order.company_id.currency_id,
to_currency=order.currency_id,
company=order.company_id,
date=order.date_order.date(),
)
@api.depends('company_id')
def _compute_has_active_pricelist(self):
+7 -13
View File
@@ -8,7 +8,7 @@ from datetime import date
from odoo import api, fields, models, _, _lt
from odoo.exceptions import ValidationError, AccessError
from odoo.osv import expression
from odoo.tools import Query, SQL
from odoo.tools import Query, SQL, OrderedSet
from odoo.addons.project.models.project_task import CLOSED_STATES
@@ -444,20 +444,17 @@ class Project(models.Model):
if sale_line_read_group:
# Get conversion rate from currencies of the sale order lines to currency of project
convert_company = self.company_id or self.env.company
currency_ids = list(set([currency_id.id for currency_id, *_ in sale_line_read_group] + [self.currency_id.id]))
rates = self.env['res.currency'].browse(currency_ids)._get_rates(convert_company, date.today())
conversion_rates = {cid: rates[self.currency_id.id] / rate_from for cid, rate_from in rates.items()}
sols_per_product = defaultdict(lambda: [0.0, 0.0, []])
downpayment_amount_invoiced = 0
downpayment_sol_ids = []
for currency, product, is_downpayment, sol_ids, untaxed_amount_to_invoice, untaxed_amount_invoiced in sale_line_read_group:
if is_downpayment:
downpayment_amount_invoiced += untaxed_amount_invoiced * conversion_rates[currency.id]
downpayment_amount_invoiced += currency._convert(untaxed_amount_invoiced, convert_company.currency_id, convert_company, round=False)
downpayment_sol_ids += sol_ids
else:
sols_per_product[product.id][0] += convert_company.currency_id.round(untaxed_amount_to_invoice * conversion_rates[currency.id])
sols_per_product[product.id][1] += convert_company.currency_id.round(untaxed_amount_invoiced * conversion_rates[currency.id])
sols_per_product[product.id][0] += currency._convert(untaxed_amount_to_invoice, convert_company.currency_id, convert_company)
sols_per_product[product.id][1] += currency._convert(untaxed_amount_invoiced, convert_company.currency_id, convert_company)
sols_per_product[product.id][2] += sol_ids
if downpayment_amount_invoiced:
downpayments_data = {
@@ -567,15 +564,12 @@ class Project(models.Model):
self._cr.execute(query_string, query_param)
invoices_move_line_read = self._cr.dictfetchall()
if invoices_move_line_read:
# Get conversion rate from currencies to currency of the current company
currency_ids = {iml['currency_id'] for iml in invoices_move_line_read + [{'currency_id': self.currency_id.id}]}
rates = self.env['res.currency'].browse(list(currency_ids))._get_rates(self.company_id or self.env.company, fields.Date.context_today(self))
conversion_rates = {cid: rates[self.currency_id.id] / rate_from for cid, rate_from in rates.items()}
currency_ids = OrderedSet(iml['currency_id'] for iml in invoices_move_line_read)
move_ids = set()
amount_invoiced = amount_to_invoice = 0.0
for moves_read in invoices_move_line_read:
price_subtotal = self.currency_id.round(moves_read['price_subtotal'] * conversion_rates[moves_read['currency_id']])
currency = self.env['res.currency'].browse(moves_read['currency_id']).with_prefetch(currency_ids)
price_subtotal = currency._convert(moves_read['price_subtotal'], self.currency_id, self.company_id)
analytic_contribution = moves_read['analytic_distribution'][str(self.analytic_account_id.id)] / 100.
move_ids.add(moves_read['move_id'])
if moves_read['parent_state'] == 'draft':
+1 -8
View File
@@ -425,16 +425,9 @@ class Project(models.Model):
costs_dict = {}
total_revenues = {'invoiced': 0.0, 'to_invoice': 0.0}
total_costs = {'billed': 0.0, 'to_bill': 0.0}
dict_rate_per_currency = {}
today = fields.Date.context_today(self)
convert_company = self.company_id or self.env.company
for timesheet_invoice_type, dummy, currency, amount, ids in aa_line_read_group:
if currency != self.currency_id:
rate = dict_rate_per_currency.get(currency.id, False)
if not rate:
rate = currency._get_conversion_rate(currency, self.currency_id, convert_company, today)
dict_rate_per_currency[currency.id] = rate
amount = self.currency_id.round(amount * rate)
amount = currency._convert(amount, self.currency_id, convert_company)
invoice_type = timesheet_invoice_type
cost = costs_dict.setdefault(invoice_type, {'billed': 0.0, 'to_bill': 0.0})
revenue = revenues_dict.setdefault(invoice_type, {'invoiced': 0.0, 'to_invoice': 0.0})