[REF] account: remove manual reconciliation widget
The manual reconciliation widget is too complex. We completely remove it and replace it with a simple wizard `account.reconcile.wizard` that opens when selected lines can't be directly/silently reconciled (then we need a write-off whose data will be filled in the wizard). To do so we had to refactor reconciliation methods to allow to shadow some values and fake reconciliation to get correct values. We also now use of the _reconcile_plan instead of the previous reconciliation which should be more efficient and correct. Refactored a bit common between `test_account_reconcile_wizard` and `test_account_move_reconcile` to avoid duplication. In this process of simplification we also separate the previous `automatic_entry_wizard` in two separate interfaces from the user's perspective: one only handle the change of period and the other will handle complex transfer that are not possible through regular reconciliation process (i.e. through the wizard we are creating in Enterprise related PR). closes odoo/odoo#120832 Task: 3060792 Related: odoo/upgrade#4674 Related: odoo/enterprise#40510 Signed-off-by: Laurent Smet <las@odoo.com>
This commit is contained in:
committed by
Laurent Smet
parent
cd20b56693
commit
f8597f3301
@@ -3941,15 +3941,7 @@ class AccountMove(models.Model):
|
||||
:param has_tax: If any taxes are involved in the lines of the invoice
|
||||
:return: a list of tuples containing the lock dates affecting this move, ordered chronologically.
|
||||
"""
|
||||
locks = []
|
||||
user_lock_date = self.company_id._get_user_fiscal_lock_date()
|
||||
if invoice_date and user_lock_date and invoice_date <= user_lock_date:
|
||||
locks.append((user_lock_date, _('user')))
|
||||
tax_lock_date = self.company_id.tax_lock_date
|
||||
if invoice_date and tax_lock_date and has_tax and invoice_date <= tax_lock_date:
|
||||
locks.append((tax_lock_date, _('tax')))
|
||||
locks.sort()
|
||||
return locks
|
||||
return self.company_id._get_violated_lock_dates(invoice_date, has_tax)
|
||||
|
||||
@api.model
|
||||
def _move_dict_to_preview_vals(self, move_vals, currency_id=None):
|
||||
|
||||
@@ -1595,30 +1595,95 @@ class AccountMoveLine(models.Model):
|
||||
# RECONCILIATION
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def _get_reconciliation_aml_field_value(self, field, shadowed_aml_values):
|
||||
self.ensure_one()
|
||||
if shadowed_aml_values and field in shadowed_aml_values.get(self, {}):
|
||||
return shadowed_aml_values[self][field]
|
||||
else:
|
||||
return self[field]
|
||||
|
||||
@api.model
|
||||
def _prepare_reconciliation_single_partial(self, debit_values, credit_values):
|
||||
""" Prepare the values to create an account.partial.reconcile later when reconciling the dictionaries passed
|
||||
as parameters, each one representing an account.move.line.
|
||||
:param debit_values: The values of account.move.line to consider for a debit line.
|
||||
:param credit_values: The values of account.move.line to consider for a credit line.
|
||||
:return: A dictionary:
|
||||
* debit_values: None if the line has nothing left to reconcile.
|
||||
* credit_values: None if the line has nothing left to reconcile.
|
||||
* partial_values: The newly computed values for the partial.
|
||||
* exchange_values: The values to create an exchange difference linked to this partial.
|
||||
def _prepare_move_line_residual_amounts(self, aml_values, counterpart_currency, shadowed_aml_values=None):
|
||||
""" Prepare the available residual amounts for each currency.
|
||||
:param aml_values: The values of account.move.line to consider.
|
||||
:param counterpart_currency: The currency of the opposite line this line will be reconciled with.
|
||||
:param shadowed_aml_values: A mapping aml -> dictionary to replace some original aml values to something else.
|
||||
This is usefull if you want to preview the reconciliation before doing some changes
|
||||
on amls like changing a date or an account.
|
||||
:return: A mapping currency -> dictionary containing:
|
||||
* residual: The residual amount left for this currency.
|
||||
* rate: The rate applied regarding the company's currency.
|
||||
"""
|
||||
|
||||
def get_odoo_rate(aml, currency):
|
||||
if aml.move_id.is_invoice(include_receipts=True):
|
||||
exchange_rate_date = aml.move_id.invoice_date
|
||||
else:
|
||||
exchange_rate_date = aml.date
|
||||
exchange_rate_date = aml._get_reconciliation_aml_field_value('date', shadowed_aml_values)
|
||||
return currency._get_conversion_rate(aml.company_currency_id, currency, aml.company_id, exchange_rate_date)
|
||||
|
||||
def get_accounting_rate(aml):
|
||||
if not aml.company_currency_id.is_zero(aml.balance) and not aml.currency_id.is_zero(aml.amount_currency):
|
||||
return abs(aml.amount_currency) / abs(aml.balance)
|
||||
def get_accounting_rate(aml, currency):
|
||||
balance = aml._get_reconciliation_aml_field_value('balance', shadowed_aml_values)
|
||||
amount_currency = aml._get_reconciliation_aml_field_value('amount_currency', shadowed_aml_values)
|
||||
if not aml.company_currency_id.is_zero(balance) and not currency.is_zero(amount_currency):
|
||||
return abs(amount_currency / balance)
|
||||
|
||||
aml = aml_values['aml']
|
||||
remaining_amount_curr = aml_values['amount_residual_currency']
|
||||
remaining_amount = aml_values['amount_residual']
|
||||
company_currency = aml.company_currency_id
|
||||
currency = aml._get_reconciliation_aml_field_value('currency_id', shadowed_aml_values)
|
||||
account = aml._get_reconciliation_aml_field_value('account_id', shadowed_aml_values)
|
||||
has_zero_residual = company_currency.is_zero(remaining_amount)
|
||||
has_zero_residual_currency = currency.is_zero(remaining_amount_curr)
|
||||
is_rec_pay_account = account.account_type in ('asset_receivable', 'liability_payable')
|
||||
|
||||
available_residual_per_currency = {}
|
||||
|
||||
if not has_zero_residual:
|
||||
available_residual_per_currency[company_currency] = {
|
||||
'residual': remaining_amount,
|
||||
'rate': 1,
|
||||
}
|
||||
if currency != company_currency and not has_zero_residual_currency:
|
||||
available_residual_per_currency[currency] = {
|
||||
'residual': remaining_amount_curr,
|
||||
'rate': get_accounting_rate(aml, currency),
|
||||
}
|
||||
|
||||
if currency == company_currency \
|
||||
and is_rec_pay_account \
|
||||
and not has_zero_residual \
|
||||
and counterpart_currency != company_currency:
|
||||
rate = get_odoo_rate(aml, counterpart_currency)
|
||||
available_residual_per_currency[counterpart_currency] = {
|
||||
'residual': counterpart_currency.round(remaining_amount * rate),
|
||||
'rate': rate,
|
||||
}
|
||||
elif currency == counterpart_currency \
|
||||
and currency != company_currency \
|
||||
and not has_zero_residual_currency:
|
||||
available_residual_per_currency[counterpart_currency] = {
|
||||
'residual': remaining_amount_curr,
|
||||
'rate': get_accounting_rate(aml, currency),
|
||||
}
|
||||
return available_residual_per_currency
|
||||
|
||||
@api.model
|
||||
def _prepare_reconciliation_single_partial(self, debit_values, credit_values, shadowed_aml_values=None):
|
||||
""" Prepare the values to create an account.partial.reconcile later when reconciling the dictionaries passed
|
||||
as parameters, each one representing an account.move.line.
|
||||
:param debit_values: The values of account.move.line to consider for a debit line.
|
||||
:param credit_values: The values of account.move.line to consider for a credit line.
|
||||
:param shadowed_aml_values: A mapping aml -> dictionary to replace some original aml values to something else.
|
||||
This is usefull if you want to preview the reconciliation before doing some changes
|
||||
on amls like changing a date or an account.
|
||||
:return: A dictionary:
|
||||
* debit_values: None if the line has nothing left to reconcile.
|
||||
* credit_values: None if the line has nothing left to reconcile.
|
||||
* partial_values: The newly computed values for the partial.
|
||||
* exchange_values: The values to create an exchange difference linked to this partial.
|
||||
"""
|
||||
# ==== Determine the currency in which the reconciliation will be done ====
|
||||
# In this part, we retrieve the residual amounts, check if they are zero or not and determine in which
|
||||
# currency and at which rate the reconciliation will be done.
|
||||
@@ -1626,95 +1691,70 @@ class AccountMoveLine(models.Model):
|
||||
'debit_values': debit_values,
|
||||
'credit_values': credit_values,
|
||||
}
|
||||
debit_aml = debit_values['aml']
|
||||
credit_aml = credit_values['aml']
|
||||
debit_currency = debit_aml._get_reconciliation_aml_field_value('currency_id', shadowed_aml_values)
|
||||
credit_currency = credit_aml._get_reconciliation_aml_field_value('currency_id', shadowed_aml_values)
|
||||
company_currency = debit_aml.company_currency_id
|
||||
|
||||
remaining_debit_amount_curr = debit_values['amount_residual_currency']
|
||||
remaining_credit_amount_curr = credit_values['amount_residual_currency']
|
||||
remaining_debit_amount = debit_values['amount_residual']
|
||||
remaining_credit_amount = credit_values['amount_residual']
|
||||
|
||||
debit_aml = debit_values['aml']
|
||||
credit_aml = credit_values['aml']
|
||||
company_currency = debit_aml.company_currency_id
|
||||
has_debit_zero_residual = company_currency.is_zero(remaining_debit_amount)
|
||||
has_credit_zero_residual = company_currency.is_zero(remaining_credit_amount)
|
||||
has_debit_zero_residual_currency = debit_aml.currency_id.is_zero(remaining_debit_amount_curr)
|
||||
has_credit_zero_residual_currency = credit_aml.currency_id.is_zero(remaining_credit_amount_curr)
|
||||
is_rec_pay_account = debit_aml.account_type in ('asset_receivable', 'liability_payable')
|
||||
debit_available_residual_amounts = self._prepare_move_line_residual_amounts(
|
||||
debit_values,
|
||||
credit_currency,
|
||||
shadowed_aml_values=shadowed_aml_values,
|
||||
)
|
||||
credit_available_residual_amounts = self._prepare_move_line_residual_amounts(
|
||||
credit_values,
|
||||
debit_currency,
|
||||
shadowed_aml_values=shadowed_aml_values,
|
||||
)
|
||||
|
||||
if debit_aml.currency_id == credit_aml.currency_id == company_currency \
|
||||
and not has_debit_zero_residual \
|
||||
and not has_credit_zero_residual:
|
||||
# Everything is expressed in company's currency and there is something left to reconcile.
|
||||
recon_currency = company_currency
|
||||
debit_rate = credit_rate = 1.0
|
||||
recon_debit_amount = remaining_debit_amount
|
||||
recon_credit_amount = -remaining_credit_amount
|
||||
elif debit_aml.currency_id == company_currency \
|
||||
and is_rec_pay_account \
|
||||
and not has_debit_zero_residual \
|
||||
and credit_aml.currency_id != company_currency \
|
||||
and not has_credit_zero_residual_currency:
|
||||
# The credit line is using a foreign currency but not the opposite line.
|
||||
# In that case, convert the amount in company currency to the foreign currency one.
|
||||
recon_currency = credit_aml.currency_id
|
||||
debit_rate = get_odoo_rate(debit_aml, recon_currency)
|
||||
credit_rate = get_accounting_rate(credit_aml)
|
||||
recon_debit_amount = recon_currency.round(remaining_debit_amount * debit_rate)
|
||||
recon_credit_amount = -remaining_credit_amount_curr
|
||||
elif debit_aml.currency_id != company_currency \
|
||||
and is_rec_pay_account \
|
||||
and not has_debit_zero_residual_currency \
|
||||
and credit_aml.currency_id == company_currency \
|
||||
and not has_credit_zero_residual:
|
||||
# The debit line is using a foreign currency but not the opposite line.
|
||||
# In that case, convert the amount in company currency to the foreign currency one.
|
||||
recon_currency = debit_aml.currency_id
|
||||
debit_rate = get_accounting_rate(debit_aml)
|
||||
credit_rate = get_odoo_rate(credit_aml, recon_currency)
|
||||
recon_debit_amount = remaining_debit_amount_curr
|
||||
recon_credit_amount = recon_currency.round(-remaining_credit_amount * credit_rate)
|
||||
elif debit_aml.currency_id == credit_aml.currency_id \
|
||||
and debit_aml.currency_id != company_currency \
|
||||
and not has_debit_zero_residual_currency \
|
||||
and not has_credit_zero_residual_currency:
|
||||
# Both lines are sharing the same foreign currency.
|
||||
recon_currency = debit_aml.currency_id
|
||||
debit_rate = get_accounting_rate(debit_aml)
|
||||
credit_rate = get_accounting_rate(credit_aml)
|
||||
recon_debit_amount = remaining_debit_amount_curr
|
||||
recon_credit_amount = -remaining_credit_amount_curr
|
||||
elif debit_aml.currency_id == credit_aml.currency_id \
|
||||
and debit_aml.currency_id != company_currency \
|
||||
and (has_debit_zero_residual_currency or has_credit_zero_residual_currency):
|
||||
# Special case for exchange difference lines. In that case, both lines are sharing the same foreign
|
||||
# currency but at least one has no amount in foreign currency.
|
||||
# In that case, we don't want a rate for the opposite line because the exchange difference is supposed
|
||||
# to reduce only the amount in company currency but not the foreign one.
|
||||
recon_currency = company_currency
|
||||
debit_rate = None
|
||||
credit_rate = None
|
||||
recon_debit_amount = remaining_debit_amount
|
||||
recon_credit_amount = -remaining_credit_amount
|
||||
if debit_currency != company_currency \
|
||||
and debit_currency in debit_available_residual_amounts \
|
||||
and debit_currency in credit_available_residual_amounts:
|
||||
recon_currency = debit_currency
|
||||
elif credit_currency != company_currency \
|
||||
and credit_currency in debit_available_residual_amounts \
|
||||
and credit_currency in credit_available_residual_amounts:
|
||||
recon_currency = credit_currency
|
||||
else:
|
||||
# Multiple involved foreign currencies. The reconciliation is done using the currency of the company.
|
||||
recon_currency = company_currency
|
||||
debit_rate = get_accounting_rate(debit_aml)
|
||||
credit_rate = get_accounting_rate(credit_aml)
|
||||
recon_debit_amount = remaining_debit_amount
|
||||
recon_credit_amount = -remaining_credit_amount
|
||||
|
||||
debit_recon_values = debit_available_residual_amounts.get(recon_currency)
|
||||
credit_recon_values = credit_available_residual_amounts.get(recon_currency)
|
||||
|
||||
# Check if there is something left to reconcile. Move to the next loop iteration if not.
|
||||
skip_reconciliation = False
|
||||
if recon_currency.is_zero(recon_debit_amount):
|
||||
if not debit_recon_values:
|
||||
res['debit_values'] = None
|
||||
skip_reconciliation = True
|
||||
if recon_currency.is_zero(recon_credit_amount):
|
||||
if not credit_recon_values:
|
||||
res['credit_values'] = None
|
||||
skip_reconciliation = True
|
||||
if skip_reconciliation:
|
||||
return res
|
||||
|
||||
recon_debit_amount = debit_recon_values['residual']
|
||||
recon_credit_amount = -credit_recon_values['residual']
|
||||
|
||||
# ==== Match both lines together and compute amounts to reconcile ====
|
||||
|
||||
# Special case for exchange difference lines. In that case, both lines are sharing the same foreign
|
||||
# currency but at least one has no amount in foreign currency.
|
||||
# In that case, we don't want a rate for the opposite line because the exchange difference is supposed
|
||||
# to reduce only the amount in company currency but not the foreign one.
|
||||
exchange_line_mode = \
|
||||
recon_currency == company_currency \
|
||||
and debit_currency == credit_currency \
|
||||
and (
|
||||
not debit_available_residual_amounts.get(debit_currency)
|
||||
or not credit_available_residual_amounts.get(credit_currency)
|
||||
)
|
||||
|
||||
# Determine which line is fully matched by the other.
|
||||
compare_amounts = recon_currency.compare_amounts(recon_debit_amount, recon_credit_amount)
|
||||
min_recon_amount = min(recon_debit_amount, recon_credit_amount)
|
||||
@@ -1723,24 +1763,38 @@ class AccountMoveLine(models.Model):
|
||||
|
||||
# ==== Computation of partial amounts ====
|
||||
if recon_currency == company_currency:
|
||||
if exchange_line_mode:
|
||||
debit_rate = None
|
||||
credit_rate = None
|
||||
else:
|
||||
debit_rate = debit_available_residual_amounts.get(debit_currency, {}).get('rate')
|
||||
credit_rate = credit_available_residual_amounts.get(credit_currency, {}).get('rate')
|
||||
|
||||
# Compute the partial amount expressed in company currency.
|
||||
partial_amount = min_recon_amount
|
||||
|
||||
# Compute the partial amount expressed in foreign currency.
|
||||
if debit_rate:
|
||||
partial_debit_amount_currency = debit_aml.currency_id.round(debit_rate * min_recon_amount)
|
||||
partial_debit_amount_currency = debit_currency.round(debit_rate * min_recon_amount)
|
||||
partial_debit_amount_currency = min(partial_debit_amount_currency, remaining_debit_amount_curr)
|
||||
else:
|
||||
partial_debit_amount_currency = 0.0
|
||||
if credit_rate:
|
||||
partial_credit_amount_currency = credit_aml.currency_id.round(credit_rate * min_recon_amount)
|
||||
partial_credit_amount_currency = credit_currency.round(credit_rate * min_recon_amount)
|
||||
partial_credit_amount_currency = min(partial_credit_amount_currency, -remaining_credit_amount_curr)
|
||||
else:
|
||||
partial_credit_amount_currency = 0.0
|
||||
|
||||
else:
|
||||
# recon_currency != company_currency
|
||||
# Compute the partial amount expressed in company currency.
|
||||
if exchange_line_mode:
|
||||
debit_rate = None
|
||||
credit_rate = None
|
||||
else:
|
||||
debit_rate = debit_recon_values['rate']
|
||||
credit_rate = credit_recon_values['rate']
|
||||
|
||||
# Compute the partial amount expressed in foreign currency.
|
||||
if debit_rate:
|
||||
partial_debit_amount = company_currency.round(min_recon_amount / debit_rate)
|
||||
partial_debit_amount = min(partial_debit_amount, remaining_debit_amount)
|
||||
@@ -1756,11 +1810,11 @@ class AccountMoveLine(models.Model):
|
||||
# Compute the partial amount expressed in foreign currency.
|
||||
# Take care to handle the case when a line expressed in company currency is mimicking the foreign
|
||||
# currency of the opposite line.
|
||||
if debit_aml.currency_id == company_currency:
|
||||
if debit_currency == company_currency:
|
||||
partial_debit_amount_currency = partial_amount
|
||||
else:
|
||||
partial_debit_amount_currency = min_recon_amount
|
||||
if credit_aml.currency_id == company_currency:
|
||||
if credit_currency == company_currency:
|
||||
partial_credit_amount_currency = partial_amount
|
||||
else:
|
||||
partial_credit_amount_currency = min_recon_amount
|
||||
@@ -1773,13 +1827,13 @@ class AccountMoveLine(models.Model):
|
||||
if recon_currency == company_currency:
|
||||
if debit_fully_matched:
|
||||
debit_exchange_amount = remaining_debit_amount_curr - partial_debit_amount_currency
|
||||
if not debit_aml.currency_id.is_zero(debit_exchange_amount):
|
||||
if not debit_currency.is_zero(debit_exchange_amount):
|
||||
exchange_lines_to_fix += debit_aml
|
||||
amounts_list.append({'amount_residual_currency': debit_exchange_amount})
|
||||
remaining_debit_amount_curr -= debit_exchange_amount
|
||||
if credit_fully_matched:
|
||||
credit_exchange_amount = remaining_credit_amount_curr + partial_credit_amount_currency
|
||||
if not credit_aml.currency_id.is_zero(credit_exchange_amount):
|
||||
if not credit_currency.is_zero(credit_exchange_amount):
|
||||
exchange_lines_to_fix += credit_aml
|
||||
amounts_list.append({'amount_residual_currency': credit_exchange_amount})
|
||||
remaining_credit_amount_curr += credit_exchange_amount
|
||||
@@ -1792,7 +1846,7 @@ class AccountMoveLine(models.Model):
|
||||
exchange_lines_to_fix += debit_aml
|
||||
amounts_list.append({'amount_residual': debit_exchange_amount})
|
||||
remaining_debit_amount -= debit_exchange_amount
|
||||
if debit_aml.currency_id == company_currency:
|
||||
if debit_currency == company_currency:
|
||||
remaining_debit_amount_curr -= debit_exchange_amount
|
||||
else:
|
||||
# Create an exchange difference ensuring the rate between the residual amounts expressed in
|
||||
@@ -1803,7 +1857,7 @@ class AccountMoveLine(models.Model):
|
||||
exchange_lines_to_fix += debit_aml
|
||||
amounts_list.append({'amount_residual': debit_exchange_amount})
|
||||
remaining_debit_amount -= debit_exchange_amount
|
||||
if debit_aml.currency_id == company_currency:
|
||||
if debit_currency == company_currency:
|
||||
remaining_debit_amount_curr -= debit_exchange_amount
|
||||
|
||||
if credit_fully_matched:
|
||||
@@ -1813,7 +1867,7 @@ class AccountMoveLine(models.Model):
|
||||
exchange_lines_to_fix += credit_aml
|
||||
amounts_list.append({'amount_residual': credit_exchange_amount})
|
||||
remaining_credit_amount += credit_exchange_amount
|
||||
if credit_aml.currency_id == company_currency:
|
||||
if credit_currency == company_currency:
|
||||
remaining_credit_amount_curr -= credit_exchange_amount
|
||||
else:
|
||||
# Create an exchange difference ensuring the rate between the residual amounts expressed in
|
||||
@@ -1824,13 +1878,16 @@ class AccountMoveLine(models.Model):
|
||||
exchange_lines_to_fix += credit_aml
|
||||
amounts_list.append({'amount_residual': credit_exchange_amount})
|
||||
remaining_credit_amount -= credit_exchange_amount
|
||||
if credit_aml.currency_id == company_currency:
|
||||
if credit_currency == company_currency:
|
||||
remaining_credit_amount_curr -= credit_exchange_amount
|
||||
|
||||
if exchange_lines_to_fix:
|
||||
res['exchange_values'] = exchange_lines_to_fix._prepare_exchange_difference_move_vals(
|
||||
amounts_list,
|
||||
exchange_date=max(debit_aml.date, credit_aml.date),
|
||||
exchange_date=max(
|
||||
debit_aml._get_reconciliation_aml_field_value('date', shadowed_aml_values),
|
||||
credit_aml._get_reconciliation_aml_field_value('date', shadowed_aml_values),
|
||||
),
|
||||
)
|
||||
|
||||
# ==== Create partials ====
|
||||
@@ -1860,16 +1917,30 @@ class AccountMoveLine(models.Model):
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def _prepare_reconciliation_amls(self, values_list):
|
||||
def _prepare_reconciliation_amls(self, values_list, shadowed_aml_values=None):
|
||||
""" Prepare the partials on the current journal items to perform the reconciliation.
|
||||
Note: The order of records in self is important because the journal items will be reconciled using this order.
|
||||
|
||||
:param values_list: A list of dictionaries, one for each aml.
|
||||
:param shadowed_aml_values: A mapping aml -> dictionary to replace some original aml values to something else.
|
||||
This is usefull if you want to preview the reconciliation before doing some changes
|
||||
on amls like changing a date or an account.
|
||||
:return: a tuple of
|
||||
1) list of vals for partial reconciliation creation,
|
||||
2) the list of vals for the exchange difference entries to be created
|
||||
"""
|
||||
debit_values_list = iter([x for x in values_list if x['aml'].balance > 0.0 or x['aml'].amount_currency > 0.0])
|
||||
credit_values_list = iter([x for x in values_list if x['aml'].balance < 0.0 or x['aml'].amount_currency < 0.0])
|
||||
debit_values_list = iter([
|
||||
x
|
||||
for x in values_list
|
||||
if x['aml']._get_reconciliation_aml_field_value('balance', shadowed_aml_values) > 0.0
|
||||
or x['aml']._get_reconciliation_aml_field_value('amount_currency', shadowed_aml_values) > 0.0
|
||||
])
|
||||
credit_values_list = iter([
|
||||
x
|
||||
for x in values_list
|
||||
if x['aml']._get_reconciliation_aml_field_value('balance', shadowed_aml_values) < 0.0
|
||||
or x['aml']._get_reconciliation_aml_field_value('amount_currency', shadowed_aml_values) < 0.0
|
||||
])
|
||||
debit_values = None
|
||||
credit_values = None
|
||||
fully_reconciled_aml_ids = set()
|
||||
@@ -1896,7 +1967,11 @@ class AccountMoveLine(models.Model):
|
||||
|
||||
# ==== Compute the amounts to reconcile ====
|
||||
|
||||
results = self._prepare_reconciliation_single_partial(debit_values, credit_values)
|
||||
results = self._prepare_reconciliation_single_partial(
|
||||
debit_values,
|
||||
credit_values,
|
||||
shadowed_aml_values=shadowed_aml_values,
|
||||
)
|
||||
if results.get('partial_values'):
|
||||
all_results.append(results)
|
||||
if results['debit_values'] is None:
|
||||
@@ -1909,11 +1984,14 @@ class AccountMoveLine(models.Model):
|
||||
return all_results, fully_reconciled_aml_ids
|
||||
|
||||
@api.model
|
||||
def _prepare_reconciliation_plan(self, plan, amls_values_map):
|
||||
def _prepare_reconciliation_plan(self, plan, amls_values_map, shadowed_aml_values=None):
|
||||
""" Perform virtually the reconciliation of the plan passed as parameter.
|
||||
|
||||
:param plan: The plan to know which lines to reconcile in which order.
|
||||
:param amls_values_map: A mapping aml => amount_residual/amount_residual_currency
|
||||
:param shadowed_aml_values: A mapping aml -> dictionary to replace some original aml values to something else.
|
||||
This is usefull if you want to preview the reconciliation before doing some changes
|
||||
on amls like changing a date or an account.
|
||||
:return: A list of all results returned by the '_prepare_reconciliation_amls' method.
|
||||
"""
|
||||
all_fully_reconciled_aml_ids = set()
|
||||
@@ -1921,10 +1999,13 @@ class AccountMoveLine(models.Model):
|
||||
|
||||
def process_amls(amls):
|
||||
remaining_amls = amls.filtered(lambda aml: aml.id not in all_fully_reconciled_aml_ids)
|
||||
amls_results, fully_reconciled_aml_ids = self._prepare_reconciliation_amls([
|
||||
amls_values_map[aml]
|
||||
for aml in remaining_amls
|
||||
])
|
||||
amls_results, fully_reconciled_aml_ids = self._prepare_reconciliation_amls(
|
||||
[
|
||||
amls_values_map[aml]
|
||||
for aml in remaining_amls
|
||||
],
|
||||
shadowed_aml_values=shadowed_aml_values,
|
||||
)
|
||||
all_fully_reconciled_aml_ids.update(fully_reconciled_aml_ids)
|
||||
for amls_result in amls_results:
|
||||
all_results.append(amls_result)
|
||||
@@ -1940,8 +2021,39 @@ class AccountMoveLine(models.Model):
|
||||
process_leaf(plan)
|
||||
return all_results
|
||||
|
||||
def _check_amls_exigibility_for_reconciliation(self, shadowed_aml_values=None):
|
||||
""" Ensure the current journal items are eligible to be reconciled together.
|
||||
:param shadowed_aml_values: A mapping aml -> dictionary to replace some original aml values to something else.
|
||||
This is usefull if you want to preview the reconciliation before doing some changes
|
||||
on amls like changing a date or an account.
|
||||
"""
|
||||
if not self:
|
||||
return
|
||||
|
||||
if any(aml.reconciled for aml in self):
|
||||
raise UserError(_("You are trying to reconcile some entries that are already reconciled."))
|
||||
if any(aml.parent_state != 'posted' for aml in self):
|
||||
raise UserError(_("You can only reconcile posted entries."))
|
||||
accounts = self.mapped(lambda x: x._get_reconciliation_aml_field_value('account_id', shadowed_aml_values))
|
||||
if len(accounts) > 1:
|
||||
raise UserError(_(
|
||||
"Entries are not from the same account: %s",
|
||||
", ".join(accounts.mapped('display_name')),
|
||||
))
|
||||
if len(self.company_id) > 1:
|
||||
raise UserError(_(
|
||||
"Entries don't belong to the same company: %s",
|
||||
", ".join(self.company_id.mapped('display_name')),
|
||||
))
|
||||
if not accounts.reconcile and accounts.account_type not in ('asset_cash', 'liability_credit_card'):
|
||||
raise UserError(_(
|
||||
"Account %s does not allow reconciliation. First change the configuration of this account "
|
||||
"to allow it.",
|
||||
accounts.display_name,
|
||||
))
|
||||
|
||||
@api.model
|
||||
def _optimize_reconciliation_plan(self, reconciliation_plan):
|
||||
def _optimize_reconciliation_plan(self, reconciliation_plan, shadowed_aml_values=None):
|
||||
""" Decode the initial reconciliation plan passed as parameter and converted it into a list of tree depicting
|
||||
the way the reconciliation should be done.
|
||||
Also, this method is responsible sorting the amls and splitting them by currency.
|
||||
@@ -1955,6 +2067,9 @@ class AccountMoveLine(models.Model):
|
||||
[[account.move.line(1, 2), account.move.line(3, 4)]]
|
||||
|
||||
:param reconciliation_plan: A list of reconciliation to perform.
|
||||
:param shadowed_aml_values: A mapping aml -> dictionary to replace some original aml values to something else.
|
||||
This is usefull if you want to preview the reconciliation before doing some changes
|
||||
on amls like changing a date or an account.
|
||||
:return: A list of dictionaries containing:
|
||||
* amls: A recordset.
|
||||
* aml_ids: The recordset ids.
|
||||
@@ -1964,18 +2079,19 @@ class AccountMoveLine(models.Model):
|
||||
def process_amls(amls):
|
||||
if self._context.get('reduced_line_sorting'):
|
||||
sorted_amls = amls.sorted(key=lambda aml: (
|
||||
aml.date_maturity or aml.date,
|
||||
aml.currency_id,
|
||||
aml._get_reconciliation_aml_field_value('date_maturity', shadowed_aml_values)
|
||||
or aml._get_reconciliation_aml_field_value('date', shadowed_aml_values),
|
||||
aml._get_reconciliation_aml_field_value('currency_id', shadowed_aml_values),
|
||||
))
|
||||
else:
|
||||
sorted_amls = amls.sorted(key=lambda aml: (
|
||||
aml.date_maturity or aml.date,
|
||||
aml.currency_id,
|
||||
aml.amount_currency,
|
||||
aml.balance,
|
||||
aml._get_reconciliation_aml_field_value('date_maturity', shadowed_aml_values)
|
||||
or aml._get_reconciliation_aml_field_value('date', shadowed_aml_values),
|
||||
aml._get_reconciliation_aml_field_value('currency_id', shadowed_aml_values),
|
||||
aml._get_reconciliation_aml_field_value('amount_currency', shadowed_aml_values),
|
||||
aml._get_reconciliation_aml_field_value('balance', shadowed_aml_values),
|
||||
))
|
||||
currencies = sorted_amls.currency_id
|
||||
|
||||
currencies = sorted_amls.mapped(lambda x: x._get_reconciliation_aml_field_value('currency_id', shadowed_aml_values))
|
||||
results = {
|
||||
'amls': sorted_amls,
|
||||
'aml_ids': set(sorted_amls.ids),
|
||||
@@ -1984,7 +2100,8 @@ class AccountMoveLine(models.Model):
|
||||
if len(currencies) != 1:
|
||||
nodes = results['nodes'] = []
|
||||
for currency in currencies:
|
||||
amls_in_currency = sorted_amls.filtered(lambda x: x.currency_id == currency)
|
||||
amls_in_currency = sorted_amls\
|
||||
.filtered(lambda x: x._get_reconciliation_aml_field_value('currency_id', shadowed_aml_values) == currency)
|
||||
nodes.append({
|
||||
'amls': amls_in_currency,
|
||||
'aml_ids': set(amls_in_currency.ids),
|
||||
@@ -2024,32 +2141,7 @@ class AccountMoveLine(models.Model):
|
||||
|
||||
# Check the amls to be reconciled all together.
|
||||
amls = plan_node['amls']
|
||||
if any(aml.reconciled for aml in amls):
|
||||
raise UserError(_("You are trying to reconcile some entries that are already reconciled."))
|
||||
if any(aml.parent_state != 'posted' for aml in amls):
|
||||
raise UserError(_("You can only reconcile posted entries."))
|
||||
if len(amls.account_id) > 1:
|
||||
raise UserError(_(
|
||||
"Entries are not from the same account: %s",
|
||||
", ".join(amls.account_id.mapped('display_name')),
|
||||
))
|
||||
if len(amls.company_id) > 1:
|
||||
raise UserError(_(
|
||||
"Entries doesn't belong to the same company: %s",
|
||||
", ".join(amls.company_id.mapped('display_name')),
|
||||
))
|
||||
|
||||
if any(
|
||||
not aml.account_id.reconcile
|
||||
and aml.account_id.account_type not in ('asset_cash', 'liability_credit_card')
|
||||
for aml in amls
|
||||
):
|
||||
raise UserError(_(
|
||||
"Account %s does not allow reconciliation. First change the configuration of this account "
|
||||
"to allow it.",
|
||||
amls.account_id.display_name
|
||||
))
|
||||
|
||||
amls._check_amls_exigibility_for_reconciliation(shadowed_aml_values=shadowed_aml_values)
|
||||
plan_list.append(plan_node)
|
||||
all_aml_ids.update(plan_node['aml_ids'])
|
||||
|
||||
@@ -2899,7 +2991,7 @@ class AccountMoveLine(models.Model):
|
||||
def action_open_business_doc(self):
|
||||
return self.move_id.action_open_business_doc()
|
||||
|
||||
def action_automatic_entry(self):
|
||||
def action_automatic_entry(self, default_action=None):
|
||||
action = self.env['ir.actions.act_window']._for_xml_id('account.account_automatic_entry_wizard_action')
|
||||
# Force the values of the move line in the context to avoid issues
|
||||
ctx = dict(self.env.context)
|
||||
@@ -2907,6 +2999,8 @@ class AccountMoveLine(models.Model):
|
||||
ctx.pop('default_journal_id', None)
|
||||
ctx['active_ids'] = self.ids
|
||||
ctx['active_model'] = 'account.move.line'
|
||||
if default_action:
|
||||
ctx['default_action'] = default_action
|
||||
action['context'] = ctx
|
||||
return action
|
||||
|
||||
|
||||
@@ -366,6 +366,23 @@ class ResCompany(models.Model):
|
||||
lock_date = self.fiscalyear_lock_date or date.min
|
||||
return lock_date
|
||||
|
||||
def _get_violated_lock_dates(self, accounting_date, has_tax):
|
||||
"""Get all the lock dates affecting the current accounting_date.
|
||||
:param accoutiaccounting_dateng_date: The accounting date
|
||||
:param has_tax: If any taxes are involved in the lines of the invoice
|
||||
:return: a list of tuples containing the lock dates ordered chronologically.
|
||||
"""
|
||||
self.ensure_one()
|
||||
locks = []
|
||||
user_lock_date = self._get_user_fiscal_lock_date()
|
||||
if accounting_date and user_lock_date and accounting_date <= user_lock_date:
|
||||
locks.append((user_lock_date, _('user')))
|
||||
tax_lock_date = self.tax_lock_date
|
||||
if accounting_date and tax_lock_date and has_tax and accounting_date <= tax_lock_date:
|
||||
locks.append((tax_lock_date, _('tax')))
|
||||
locks.sort()
|
||||
return locks
|
||||
|
||||
def write(self, values):
|
||||
#restrict the closing of FY if there are still unposted entries
|
||||
self._validate_fiscalyear_lock(values)
|
||||
|
||||
+35
-165
@@ -413,6 +413,41 @@ class AccountTestInvoicingCommon(TransactionCase):
|
||||
|
||||
return rslt
|
||||
|
||||
def create_line_for_reconciliation(self, balance, amount_currency, currency, move_date, account_1=None, partner=None):
|
||||
write_off_account_to_be_reconciled = account_1 if account_1 else self.receivable_account
|
||||
move = self.env['account.move'].create({
|
||||
'move_type': 'entry',
|
||||
'date': move_date,
|
||||
'line_ids': [
|
||||
Command.create({
|
||||
'debit': balance if balance > 0.0 else 0.0,
|
||||
'credit': -balance if balance < 0.0 else 0.0,
|
||||
'amount_currency': amount_currency,
|
||||
'account_id': write_off_account_to_be_reconciled.id,
|
||||
'currency_id': currency.id,
|
||||
'partner_id': partner.id if partner else None,
|
||||
}),
|
||||
Command.create({
|
||||
'debit': -balance if balance < 0.0 else 0.0,
|
||||
'credit': balance if balance > 0.0 else 0.0,
|
||||
'amount_currency': -amount_currency,
|
||||
'account_id': self.revenue_account.id,
|
||||
'currency_id': currency.id,
|
||||
'partner_id': partner.id if partner else None,
|
||||
}),
|
||||
],
|
||||
})
|
||||
move.action_post()
|
||||
line = move.line_ids.filtered(lambda x: x.account_id == write_off_account_to_be_reconciled)
|
||||
|
||||
self.assertRecordValues(line, [{
|
||||
'amount_residual': balance,
|
||||
'amount_residual_currency': amount_currency,
|
||||
'reconciled': False,
|
||||
}])
|
||||
|
||||
return line
|
||||
|
||||
def assertInvoiceValues(self, move, expected_lines_values, expected_move_values):
|
||||
def sort_lines(lines):
|
||||
return lines.sorted(lambda line: (line.sequence, not bool(line.tax_line_id), line.name or '', line.balance))
|
||||
@@ -541,168 +576,3 @@ class AccountTestInvoicingCommon(TransactionCase):
|
||||
|
||||
class AccountTestInvoicingHttpCommon(AccountTestInvoicingCommon, HttpCase):
|
||||
pass
|
||||
|
||||
|
||||
class TestAccountReconciliationCommon(AccountTestInvoicingCommon):
|
||||
|
||||
"""Tests for reconciliation (account.tax)
|
||||
|
||||
Test used to check that when doing a sale or purchase invoice in a different currency,
|
||||
the result will be balanced.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls, chart_template_ref=None):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
cls.company = cls.company_data['company']
|
||||
cls.company.currency_id = cls.env.ref('base.EUR')
|
||||
|
||||
cls.partner_agrolait = cls.env['res.partner'].create({
|
||||
'name': 'Deco Addict',
|
||||
'is_company': True,
|
||||
'country_id': cls.env.ref('base.us').id,
|
||||
})
|
||||
cls.partner_agrolait_id = cls.partner_agrolait.id
|
||||
cls.currency_swiss_id = cls.env.ref("base.CHF").id
|
||||
cls.currency_usd_id = cls.env.ref("base.USD").id
|
||||
cls.currency_euro_id = cls.env.ref("base.EUR").id
|
||||
cls.account_rcv = cls.company_data['default_account_receivable']
|
||||
cls.account_rsa = cls.company_data['default_account_payable']
|
||||
cls.product = cls.env['product.product'].create({
|
||||
'name': 'Product Product 4',
|
||||
'standard_price': 500.0,
|
||||
'list_price': 750.0,
|
||||
'type': 'consu',
|
||||
'categ_id': cls.env.ref('product.product_category_all').id,
|
||||
})
|
||||
|
||||
cls.bank_journal_euro = cls.env['account.journal'].create({'name': 'Bank', 'type': 'bank', 'code': 'BNK67'})
|
||||
cls.account_euro = cls.bank_journal_euro.default_account_id
|
||||
|
||||
cls.bank_journal_usd = cls.env['account.journal'].create({'name': 'Bank US', 'type': 'bank', 'code': 'BNK68', 'currency_id': cls.currency_usd_id})
|
||||
cls.account_usd = cls.bank_journal_usd.default_account_id
|
||||
|
||||
cls.fx_journal = cls.company.currency_exchange_journal_id
|
||||
cls.diff_income_account = cls.company.income_currency_exchange_account_id
|
||||
cls.diff_expense_account = cls.company.expense_currency_exchange_account_id
|
||||
|
||||
cls.expense_account = cls.company_data['default_account_expense']
|
||||
# cash basis intermediary account
|
||||
cls.tax_waiting_account = cls.env['account.account'].create({
|
||||
'name': 'TAX_WAIT',
|
||||
'code': 'TWAIT',
|
||||
'account_type': 'liability_current',
|
||||
'reconcile': True,
|
||||
'company_id': cls.company.id,
|
||||
})
|
||||
# cash basis final account
|
||||
cls.tax_final_account = cls.env['account.account'].create({
|
||||
'name': 'TAX_TO_DEDUCT',
|
||||
'code': 'TDEDUCT',
|
||||
'account_type': 'asset_current',
|
||||
'company_id': cls.company.id,
|
||||
})
|
||||
cls.tax_base_amount_account = cls.env['account.account'].create({
|
||||
'name': 'TAX_BASE',
|
||||
'code': 'TBASE',
|
||||
'account_type': 'asset_current',
|
||||
'company_id': cls.company.id,
|
||||
})
|
||||
cls.company.account_cash_basis_base_account_id = cls.tax_base_amount_account.id
|
||||
|
||||
|
||||
# Journals
|
||||
cls.purchase_journal = cls.company_data['default_journal_purchase']
|
||||
cls.cash_basis_journal = cls.env['account.journal'].create({
|
||||
'name': 'Test CABA',
|
||||
'code': 'tCABA',
|
||||
'type': 'general',
|
||||
})
|
||||
cls.general_journal = cls.company_data['default_journal_misc']
|
||||
|
||||
# Tax Cash Basis
|
||||
cls.tax_cash_basis = cls.env['account.tax'].create({
|
||||
'name': 'cash basis 20%',
|
||||
'type_tax_use': 'purchase',
|
||||
'company_id': cls.company.id,
|
||||
'country_id': cls.company.account_fiscal_country_id.id,
|
||||
'amount': 20,
|
||||
'tax_exigibility': 'on_payment',
|
||||
'cash_basis_transition_account_id': cls.tax_waiting_account.id,
|
||||
'invoice_repartition_line_ids': [
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': cls.tax_final_account.id,
|
||||
}),
|
||||
],
|
||||
'refund_repartition_line_ids': [
|
||||
(0,0, {
|
||||
'repartition_type': 'base',
|
||||
}),
|
||||
|
||||
(0,0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': cls.tax_final_account.id,
|
||||
}),
|
||||
],
|
||||
})
|
||||
cls.env['res.currency.rate'].create([
|
||||
{
|
||||
'currency_id': cls.env.ref('base.EUR').id,
|
||||
'name': '2010-01-02',
|
||||
'rate': 1.0,
|
||||
}, {
|
||||
'currency_id': cls.env.ref('base.USD').id,
|
||||
'name': '2010-01-02',
|
||||
'rate': 1.2834,
|
||||
}, {
|
||||
'currency_id': cls.env.ref('base.USD').id,
|
||||
'name': time.strftime('%Y-06-05'),
|
||||
'rate': 1.5289,
|
||||
}
|
||||
])
|
||||
|
||||
def _create_invoice(self, move_type='out_invoice', invoice_amount=50, currency_id=None, partner_id=None, date_invoice=None, payment_term_id=False, auto_validate=False):
|
||||
date_invoice = date_invoice or time.strftime('%Y') + '-07-01'
|
||||
|
||||
invoice_vals = {
|
||||
'move_type': move_type,
|
||||
'partner_id': partner_id or self.partner_agrolait_id,
|
||||
'invoice_date': date_invoice,
|
||||
'date': date_invoice,
|
||||
'invoice_line_ids': [(0, 0, {
|
||||
'name': 'product that cost %s' % invoice_amount,
|
||||
'quantity': 1,
|
||||
'price_unit': invoice_amount,
|
||||
'tax_ids': [Command.set([])],
|
||||
})]
|
||||
}
|
||||
|
||||
if payment_term_id:
|
||||
invoice_vals['invoice_payment_term_id'] = payment_term_id
|
||||
|
||||
if currency_id:
|
||||
invoice_vals['currency_id'] = currency_id
|
||||
|
||||
invoice = self.env['account.move'].with_context(default_move_type=move_type).create(invoice_vals)
|
||||
if auto_validate:
|
||||
invoice.action_post()
|
||||
return invoice
|
||||
|
||||
def create_invoice(self, move_type='out_invoice', invoice_amount=50, currency_id=None):
|
||||
return self._create_invoice(move_type=move_type, invoice_amount=invoice_amount, currency_id=currency_id, auto_validate=True)
|
||||
|
||||
def create_invoice_partner(self, move_type='out_invoice', invoice_amount=50, currency_id=None, partner_id=False, payment_term_id=False):
|
||||
return self._create_invoice(
|
||||
move_type=move_type,
|
||||
invoice_amount=invoice_amount,
|
||||
currency_id=currency_id,
|
||||
partner_id=partner_id,
|
||||
payment_term_id=payment_term_id,
|
||||
auto_validate=True
|
||||
)
|
||||
|
||||
@@ -19,6 +19,10 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
cls.receivable_account = cls.company_data['default_account_receivable']
|
||||
cls.payable_account = cls.company_data['default_account_payable']
|
||||
cls.expense_account = cls.company_data['default_account_expense']
|
||||
cls.revenue_account = cls.company_data['default_account_revenue']
|
||||
|
||||
cls.extra_receivable_account_1 = cls.copy_account(cls.receivable_account)
|
||||
cls.extra_receivable_account_2 = cls.copy_account(cls.receivable_account)
|
||||
cls.extra_payable_account_1 = cls.copy_account(cls.company_data['default_account_payable'])
|
||||
@@ -27,6 +31,7 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
cls.exch_income_account = cls.env.company.income_currency_exchange_account_id
|
||||
cls.exch_expense_account = cls.env.company.expense_currency_exchange_account_id
|
||||
|
||||
|
||||
# ==== Multi-currency setup ====
|
||||
|
||||
cls.currency_data_2 = cls.setup_multi_currency_data(default_values={
|
||||
@@ -207,38 +212,6 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
def _get_caba_moves(self, moves):
|
||||
return moves.search([('tax_cash_basis_origin_move_id', 'in', moves.ids)])
|
||||
|
||||
def _create_line_for_reconciliation(self, balance, amount_currency, currency, move_date):
|
||||
move = self.env['account.move'].create({
|
||||
'move_type': 'entry',
|
||||
'date': move_date,
|
||||
'line_ids': [
|
||||
Command.create({
|
||||
'debit': balance if balance > 0.0 else 0.0,
|
||||
'credit': -balance if balance < 0.0 else 0.0,
|
||||
'amount_currency': amount_currency,
|
||||
'account_id': self.receivable_account.id,
|
||||
'currency_id': currency.id,
|
||||
}),
|
||||
Command.create({
|
||||
'debit': -balance if balance < 0.0 else 0.0,
|
||||
'credit': balance if balance > 0.0 else 0.0,
|
||||
'amount_currency': -amount_currency,
|
||||
'account_id': self.company_data['default_account_revenue'].id,
|
||||
'currency_id': currency.id,
|
||||
}),
|
||||
],
|
||||
})
|
||||
move.action_post()
|
||||
line = move.line_ids.filtered(lambda x: x.account_id == self.receivable_account)
|
||||
|
||||
self.assertRecordValues(line, [{
|
||||
'amount_residual': balance,
|
||||
'amount_residual_currency': amount_currency,
|
||||
'reconciled': False,
|
||||
}])
|
||||
|
||||
return line
|
||||
|
||||
def test_full_reconcile_bunch_lines(self):
|
||||
""" Test the reconciliation with multiple lines at the same time and ensure the result is always a full
|
||||
reconcile whatever the number of involved currencies.
|
||||
@@ -247,25 +220,25 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
foreign_curr1 = self.currency_data['currency']
|
||||
foreign_curr2 = self.currency_data_2['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(1000.0, 1000.0, comp_curr, '2016-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(-300.0, -300.0, comp_curr, '2016-01-01')
|
||||
line_3 = self._create_line_for_reconciliation(-400.0, -400.0, comp_curr, '2016-01-01')
|
||||
line_4 = self._create_line_for_reconciliation(-500.0, -500.0, comp_curr, '2016-01-01')
|
||||
line_5 = self._create_line_for_reconciliation(200.0, 200.0, comp_curr, '2016-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(1000.0, 1000.0, comp_curr, '2016-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(-300.0, -300.0, comp_curr, '2016-01-01')
|
||||
line_3 = self.create_line_for_reconciliation(-400.0, -400.0, comp_curr, '2016-01-01')
|
||||
line_4 = self.create_line_for_reconciliation(-500.0, -500.0, comp_curr, '2016-01-01')
|
||||
line_5 = self.create_line_for_reconciliation(200.0, 200.0, comp_curr, '2016-01-01')
|
||||
comp_curr_batch = line_1 + line_2 + line_3 + line_4 + line_5
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(1200.0, 3600.0, foreign_curr1, '2016-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(-240.0, -480.0, foreign_curr1, '2017-01-01')
|
||||
line_3 = self._create_line_for_reconciliation(-720.0, -1440.0, foreign_curr1, '2017-01-01')
|
||||
line_4 = self._create_line_for_reconciliation(-1020.0, -2040.0, foreign_curr1, '2017-01-01')
|
||||
line_5 = self._create_line_for_reconciliation(120.0, 360.0, foreign_curr1, '2016-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(1200.0, 3600.0, foreign_curr1, '2016-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(-240.0, -480.0, foreign_curr1, '2017-01-01')
|
||||
line_3 = self.create_line_for_reconciliation(-720.0, -1440.0, foreign_curr1, '2017-01-01')
|
||||
line_4 = self.create_line_for_reconciliation(-1020.0, -2040.0, foreign_curr1, '2017-01-01')
|
||||
line_5 = self.create_line_for_reconciliation(120.0, 360.0, foreign_curr1, '2016-01-01')
|
||||
same_curr_batch = line_1 + line_2 + line_3 + line_4 + line_5
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(1200.0, 3600.0, foreign_curr1, '2016-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(780.0, 2340.0, foreign_curr1, '2016-01-01')
|
||||
line_3 = self._create_line_for_reconciliation(-240.0, -960.0, foreign_curr2, '2017-01-01')
|
||||
line_4 = self._create_line_for_reconciliation(-720.0, -2880.0, foreign_curr2, '2017-01-01')
|
||||
line_5 = self._create_line_for_reconciliation(-1020.0, -4080.0, foreign_curr2, '2017-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(1200.0, 3600.0, foreign_curr1, '2016-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(780.0, 2340.0, foreign_curr1, '2016-01-01')
|
||||
line_3 = self.create_line_for_reconciliation(-240.0, -960.0, foreign_curr2, '2017-01-01')
|
||||
line_4 = self.create_line_for_reconciliation(-720.0, -2880.0, foreign_curr2, '2017-01-01')
|
||||
line_5 = self.create_line_for_reconciliation(-1020.0, -4080.0, foreign_curr2, '2017-01-01')
|
||||
multi_curr_batch = line_1 + line_2 + line_3 + line_4 + line_5
|
||||
|
||||
for batch, sub_test_name in (
|
||||
@@ -292,9 +265,9 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
for rate2 in rates:
|
||||
for rate3 in rates:
|
||||
with self.subTest(rate1=rate1, rate2=rate2, rate3=rate3):
|
||||
line_1 = self._create_line_for_reconciliation(120.0 * rate1, 120.0, currency, '2017-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(120.0 * rate2, 120.0, currency, '2017-01-01')
|
||||
line_3 = self._create_line_for_reconciliation(-240.0 * rate3, -240.0, currency, '2017-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(120.0 * rate1, 120.0, currency, '2017-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(120.0 * rate2, 120.0, currency, '2017-01-01')
|
||||
line_3 = self.create_line_for_reconciliation(-240.0 * rate3, -240.0, currency, '2017-01-01')
|
||||
|
||||
(line_1 + line_2 + line_3).reconcile()
|
||||
self.assertTrue(line_1.full_reconcile_id)
|
||||
@@ -312,8 +285,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
((60.0, 60.0, comp_curr, '2017-01-01'), (-40.0, -120.0, foreign_curr, '2016-01-01')),
|
||||
((-60.0, -60.0, comp_curr, '2017-01-01'), (40.0, 120.0, foreign_curr, '2016-01-01')),
|
||||
):
|
||||
line1 = self._create_line_for_reconciliation(*line1_vals)
|
||||
line2 = self._create_line_for_reconciliation(*line2_vals)
|
||||
line1 = self.create_line_for_reconciliation(*line1_vals)
|
||||
line2 = self.create_line_for_reconciliation(*line2_vals)
|
||||
with self.subTest(line1_vals=line1_vals, line2_vals=line2_vals):
|
||||
(line1 + line2).reconcile()
|
||||
|
||||
@@ -368,13 +341,13 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
an additional move is added with the right foreign currency amount. """
|
||||
currency = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(0.0, -0.02, currency, '2017-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(0.0, 0.01, currency, '2017-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(0.0, -0.02, currency, '2017-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(0.0, 0.01, currency, '2017-01-01')
|
||||
(line_1 + line_2).reconcile()
|
||||
|
||||
self.assertFalse(line_1.full_reconcile_id + line_2.full_reconcile_id, "The reconciliation should not be considered full, as 0.01 still remain open in foreign currency.")
|
||||
|
||||
line_3 = self._create_line_for_reconciliation(0.0, 0.01, currency, '2017-01-01')
|
||||
line_3 = self.create_line_for_reconciliation(0.0, 0.01, currency, '2017-01-01')
|
||||
(line_1 + line_3).reconcile()
|
||||
|
||||
self.assertTrue(line_1.full_reconcile_id)
|
||||
@@ -393,8 +366,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
'currency_subunit_label': 'Bretonnian Denier',
|
||||
})['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(0.0, -0.01, currency_1, '2017-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(0.0, 0.02, currency_2, '2016-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(0.0, -0.01, currency_1, '2017-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(0.0, 0.02, currency_2, '2016-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -412,8 +385,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
"""
|
||||
currency = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(-0.01, 0.0, currency, '2017-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(0.02, 0.0, currency, '2016-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(-0.01, 0.0, currency, '2017-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(0.02, 0.0, currency, '2016-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -467,8 +440,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
comp_curr = self.company_data['currency']
|
||||
foreign_curr = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(-0.01, -0.01, comp_curr, '2017-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(0.0, 0.03, foreign_curr, '2016-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(-0.01, -0.01, comp_curr, '2017-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(0.0, 0.03, foreign_curr, '2016-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -542,8 +515,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
foreign_curr1 = self.currency_data['currency']
|
||||
foreign_curr2 = self.currency_data_2['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(-0.01, 0.0, foreign_curr2, '2017-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(0.01, 0.03, foreign_curr1, '2016-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(-0.01, 0.0, foreign_curr2, '2017-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(0.01, 0.03, foreign_curr1, '2016-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -572,8 +545,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
"""
|
||||
currency = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(-0.06, 0.0, currency, '2017-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(0.12, 0.24, currency, '2017-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(-0.06, 0.0, currency, '2017-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(0.12, 0.24, currency, '2017-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -596,8 +569,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
def test_reconcile_exchange_difference_on_partial_same_foreign_currency_debit_expense_partial_payment(self):
|
||||
currency = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(60.0, 120.0, currency, '2017-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(-80.0, -240.0, currency, '2016-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(60.0, 120.0, currency, '2017-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(-80.0, -240.0, currency, '2016-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -644,8 +617,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
def test_reconcile_exchange_difference_on_partial_same_foreign_currency_debit_income_partial_payment(self):
|
||||
currency = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(40.0, 120.0, currency, '2016-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(-120.0, -240.0, currency, '2017-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(40.0, 120.0, currency, '2016-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(-120.0, -240.0, currency, '2017-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -692,8 +665,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
def test_reconcile_exchange_difference_on_partial_same_foreign_currency_credit_expense_partial_payment(self):
|
||||
currency = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(-40.0, -120.0, currency, '2016-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(120.0, 240.0, currency, '2017-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(-40.0, -120.0, currency, '2016-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(120.0, 240.0, currency, '2017-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -740,8 +713,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
def test_reconcile_exchange_difference_on_partial_same_foreign_currency_credit_income_partial_payment(self):
|
||||
currency = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(-60.0, -120.0, currency, '2017-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(80.0, 240.0, currency, '2016-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(-60.0, -120.0, currency, '2017-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(80.0, 240.0, currency, '2016-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -789,8 +762,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
comp_curr = self.company_data['currency']
|
||||
foreign_curr = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(60.0, 120.0, foreign_curr, '2017-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(-80.0, -80.0, comp_curr, '2016-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(60.0, 120.0, foreign_curr, '2017-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(-80.0, -80.0, comp_curr, '2016-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -838,8 +811,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
comp_curr = self.company_data['currency']
|
||||
foreign_curr = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(60.0, 60.0, comp_curr, '2017-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(-80.0, -240.0, foreign_curr, '2016-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(60.0, 60.0, comp_curr, '2017-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(-80.0, -240.0, foreign_curr, '2016-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -887,8 +860,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
comp_curr = self.company_data['currency']
|
||||
foreign_curr = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(40.0, 120.0, foreign_curr, '2016-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(-120.0, -120.0, comp_curr, '2017-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(40.0, 120.0, foreign_curr, '2016-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(-120.0, -120.0, comp_curr, '2017-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -936,8 +909,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
comp_curr = self.company_data['currency']
|
||||
foreign_curr = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(40.0, 40.0, comp_curr, '2016-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(-120.0, -240.0, foreign_curr, '2017-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(40.0, 40.0, comp_curr, '2016-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(-120.0, -240.0, foreign_curr, '2017-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -985,8 +958,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
comp_curr = self.company_data['currency']
|
||||
foreign_curr = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(-40.0, -120.0, foreign_curr, '2016-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(120.0, 120.0, comp_curr, '2017-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(-40.0, -120.0, foreign_curr, '2016-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(120.0, 120.0, comp_curr, '2017-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -1034,8 +1007,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
comp_curr = self.company_data['currency']
|
||||
foreign_curr = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(-40.0, -40.0, comp_curr, '2016-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(120.0, 240.0, foreign_curr, '2017-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(-40.0, -40.0, comp_curr, '2016-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(120.0, 240.0, foreign_curr, '2017-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -1083,8 +1056,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
comp_curr = self.company_data['currency']
|
||||
foreign_curr = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(-60.0, -60.0, comp_curr, '2017-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(80.0, 240.0, foreign_curr, '2016-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(-60.0, -60.0, comp_curr, '2017-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(80.0, 240.0, foreign_curr, '2016-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -1132,8 +1105,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
comp_curr = self.company_data['currency']
|
||||
foreign_curr = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(-60.0, -120.0, foreign_curr, '2017-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(80.0, 80.0, comp_curr, '2016-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(-60.0, -120.0, foreign_curr, '2017-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(80.0, 80.0, comp_curr, '2016-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -1180,8 +1153,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
def test_reconcile_exchange_difference_on_partial_same_foreign_currency_debit_expense_full_payment(self):
|
||||
currency = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(60.0, 120.0, currency, '2017-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(-40.0, -120.0, currency, '2016-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(60.0, 120.0, currency, '2017-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(-40.0, -120.0, currency, '2016-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -1231,8 +1204,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
def test_reconcile_exchange_difference_on_partial_same_foreign_currency_debit_income_full_payment(self):
|
||||
currency = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(40.0, 120.0, currency, '2016-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(-60.0, -120.0, currency, '2017-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(40.0, 120.0, currency, '2016-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(-60.0, -120.0, currency, '2017-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -1282,8 +1255,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
def test_reconcile_exchange_difference_on_partial_same_foreign_currency_credit_expense_full_payment(self):
|
||||
currency = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(-40.0, -120.0, currency, '2016-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(60.0, 120.0, currency, '2017-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(-40.0, -120.0, currency, '2016-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(60.0, 120.0, currency, '2017-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -1333,8 +1306,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
def test_reconcile_exchange_difference_on_partial_same_foreign_currency_credit_income_full_payment(self):
|
||||
currency = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(-60.0, -120.0, currency, '2017-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(40.0, 120.0, currency, '2016-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(-60.0, -120.0, currency, '2017-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(40.0, 120.0, currency, '2016-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -1385,8 +1358,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
comp_curr = self.company_data['currency']
|
||||
foreign_curr = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(60.0, 120.0, foreign_curr, '2017-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(-40.0, -40.0, comp_curr, '2016-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(60.0, 120.0, foreign_curr, '2017-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(-40.0, -40.0, comp_curr, '2016-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -1437,8 +1410,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
comp_curr = self.company_data['currency']
|
||||
foreign_curr = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(60.0, 60.0, comp_curr, '2017-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(-40.0, -120.0, foreign_curr, '2016-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(60.0, 60.0, comp_curr, '2017-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(-40.0, -120.0, foreign_curr, '2016-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -1489,8 +1462,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
comp_curr = self.company_data['currency']
|
||||
foreign_curr = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(40.0, 120.0, foreign_curr, '2016-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(-60.0, -60.0, comp_curr, '2017-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(40.0, 120.0, foreign_curr, '2016-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(-60.0, -60.0, comp_curr, '2017-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -1541,8 +1514,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
comp_curr = self.company_data['currency']
|
||||
foreign_curr = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(40.0, 40.0, comp_curr, '2016-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(-60.0, -120.0, foreign_curr, '2017-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(40.0, 40.0, comp_curr, '2016-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(-60.0, -120.0, foreign_curr, '2017-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -1593,8 +1566,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
comp_curr = self.company_data['currency']
|
||||
foreign_curr = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(-40.0, -40.0, comp_curr, '2016-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(60.0, 120.0, foreign_curr, '2017-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(-40.0, -40.0, comp_curr, '2016-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(60.0, 120.0, foreign_curr, '2017-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -1645,8 +1618,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
comp_curr = self.company_data['currency']
|
||||
foreign_curr = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(-40.0, -120.0, foreign_curr, '2016-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(60.0, 60.0, comp_curr, '2017-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(-40.0, -120.0, foreign_curr, '2016-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(60.0, 60.0, comp_curr, '2017-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -1697,8 +1670,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
comp_curr = self.company_data['currency']
|
||||
foreign_curr = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(-60.0, -60.0, comp_curr, '2017-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(40.0, 120.0, foreign_curr, '2016-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(-60.0, -60.0, comp_curr, '2017-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(40.0, 120.0, foreign_curr, '2016-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -1749,8 +1722,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
comp_curr = self.company_data['currency']
|
||||
foreign_curr = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(-60.0, -120.0, foreign_curr, '2017-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(40.0, 40.0, comp_curr, '2016-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(-60.0, -120.0, foreign_curr, '2017-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(40.0, 40.0, comp_curr, '2016-01-01')
|
||||
amls = line_1 + line_2
|
||||
|
||||
amls.reconcile()
|
||||
@@ -2459,8 +2432,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
def test_migration_to_new_reconciliation_same_foreign_currency(self):
|
||||
foreign_curr = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(-60.0, -120.0, foreign_curr, '2017-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(80.0, 240.0, foreign_curr, '2016-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(-60.0, -120.0, foreign_curr, '2017-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(80.0, 240.0, foreign_curr, '2016-01-01')
|
||||
|
||||
# Create the partial as it should be created in previous version.
|
||||
self.env['account.partial.reconcile'].create({
|
||||
@@ -2476,14 +2449,14 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
])
|
||||
|
||||
# Reconcile using the "new" reconciliation.
|
||||
line_3 = self._create_line_for_reconciliation(-15.0, -30.0, foreign_curr, '2017-01-01')
|
||||
line_3 = self.create_line_for_reconciliation(-15.0, -30.0, foreign_curr, '2017-01-01')
|
||||
(line_2 + line_3).reconcile()
|
||||
self.assertRecordValues(line_2 + line_3, [
|
||||
{'amount_residual': 10.0, 'amount_residual_currency': 90.0, 'reconciled': False},
|
||||
{'amount_residual': 0.0, 'amount_residual_currency': 0.0, 'reconciled': True},
|
||||
])
|
||||
|
||||
line_4 = self._create_line_for_reconciliation(-30.0, -90.0, foreign_curr, '2016-01-01')
|
||||
line_4 = self.create_line_for_reconciliation(-30.0, -90.0, foreign_curr, '2016-01-01')
|
||||
(line_2 + line_4).reconcile()
|
||||
self.assertRecordValues(line_2 + line_4, [
|
||||
{'amount_residual': 0.0, 'amount_residual_currency': 0.0, 'reconciled': True},
|
||||
@@ -2494,9 +2467,9 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
comp_curr = self.company_data['currency']
|
||||
foreign_curr1 = self.currency_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(600.0, 1200.0, foreign_curr1, '2017-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(-800.0, -2400.0, foreign_curr1, '2016-01-01')
|
||||
line_3 = self._create_line_for_reconciliation(400.0, 400.0, comp_curr, '2016-01-01')
|
||||
line_1 = self.create_line_for_reconciliation(600.0, 1200.0, foreign_curr1, '2017-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(-800.0, -2400.0, foreign_curr1, '2016-01-01')
|
||||
line_3 = self.create_line_for_reconciliation(400.0, 400.0, comp_curr, '2016-01-01')
|
||||
|
||||
# Create the partials as it should be created in previous version.
|
||||
self.env['account.partial.reconcile'].create([
|
||||
@@ -2522,8 +2495,8 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
])
|
||||
|
||||
# Fix 'line_2' & 'line_4' using the "new" reconciliation.
|
||||
line_4 = self._create_line_for_reconciliation(0.0, 600.0, foreign_curr1, '2016-01-01')
|
||||
line_5 = self._create_line_for_reconciliation(-200.0, -200.0, comp_curr, '2016-01-01')
|
||||
line_4 = self.create_line_for_reconciliation(0.0, 600.0, foreign_curr1, '2016-01-01')
|
||||
line_5 = self.create_line_for_reconciliation(-200.0, -200.0, comp_curr, '2016-01-01')
|
||||
(line_2 + line_3 + line_4 + line_5).reconcile()
|
||||
|
||||
self.assertRecordValues(line_1 + line_2 + line_3 + line_4 + line_5, [
|
||||
@@ -2576,11 +2549,11 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
|
||||
comp_curr = self.company_data['currency']
|
||||
|
||||
line_1 = self._create_line_for_reconciliation(600.0, 600.0, comp_curr, '2017-01-01')
|
||||
line_2 = self._create_line_for_reconciliation(-100.0, -100.0, comp_curr, '2017-01-02')
|
||||
line_3 = self._create_line_for_reconciliation(700.0, 700.0, comp_curr, '2017-01-03')
|
||||
line_5 = self._create_line_for_reconciliation(-700.0, -700.0, comp_curr, '2017-01-04')
|
||||
line_4 = self._create_line_for_reconciliation(-500.0, -500.0, comp_curr, '2017-01-05')
|
||||
line_1 = self.create_line_for_reconciliation(600.0, 600.0, comp_curr, '2017-01-01')
|
||||
line_2 = self.create_line_for_reconciliation(-100.0, -100.0, comp_curr, '2017-01-02')
|
||||
line_3 = self.create_line_for_reconciliation(700.0, 700.0, comp_curr, '2017-01-03')
|
||||
line_5 = self.create_line_for_reconciliation(-700.0, -700.0, comp_curr, '2017-01-04')
|
||||
line_4 = self.create_line_for_reconciliation(-500.0, -500.0, comp_curr, '2017-01-05')
|
||||
|
||||
with rollback():
|
||||
# 5 batches of 1 aml. This won't reconcile anything.
|
||||
|
||||
@@ -195,9 +195,8 @@ class TestTransferWizard(AccountTestInvoicingCommon):
|
||||
active_move_lines = (self.move_1 + self.move_2).mapped('line_ids').filtered(lambda x: x.account_id.account_type in ('asset_receivable', 'liability_payable'))
|
||||
|
||||
# We use a form to pass the context properly to the depends_context move_line_ids field
|
||||
context = {'active_model': 'account.move.line', 'active_ids': active_move_lines.ids}
|
||||
context = {'active_model': 'account.move.line', 'active_ids': active_move_lines.ids, 'default_action': 'change_account'}
|
||||
with Form(self.env['account.automatic.entry.wizard'].with_context(context)) as wizard_form:
|
||||
wizard_form.action = 'change_account'
|
||||
wizard_form.destination_account_id = self.receivable_account
|
||||
wizard_form.journal_id = self.journal
|
||||
wizard = wizard_form.save()
|
||||
@@ -221,9 +220,8 @@ class TestTransferWizard(AccountTestInvoicingCommon):
|
||||
active_move_lines = (self.move_1 + self.move_2).mapped('line_ids').filtered(lambda x: x.name in ('test1_3', 'test1_4', 'test1_5', 'test2_3', 'test2_4', 'test2_5', 'test2_6', 'test2_8'))
|
||||
|
||||
# We use a form to pass the context properly to the depends_context move_line_ids field
|
||||
context = {'active_model': 'account.move.line', 'active_ids': active_move_lines.ids}
|
||||
context = {'active_model': 'account.move.line', 'active_ids': active_move_lines.ids, 'default_action': 'change_account'}
|
||||
with Form(self.env['account.automatic.entry.wizard'].with_context(context)) as wizard_form:
|
||||
wizard_form.action = 'change_account'
|
||||
wizard_form.destination_account_id = self.accounts[4]
|
||||
wizard_form.journal_id = self.journal
|
||||
wizard = wizard_form.save()
|
||||
@@ -252,9 +250,8 @@ class TestTransferWizard(AccountTestInvoicingCommon):
|
||||
active_move_lines = self.move_1.mapped('line_ids').filtered(lambda x: x.name in ('test1_6', 'test1_9'))
|
||||
|
||||
# We use a form to pass the context properly to the depends_context move_line_ids field
|
||||
context = {'active_model': 'account.move.line', 'active_ids': active_move_lines.ids}
|
||||
context = {'active_model': 'account.move.line', 'active_ids': active_move_lines.ids, 'default_action': 'change_account'}
|
||||
with Form(self.env['account.automatic.entry.wizard'].with_context(context)) as wizard_form:
|
||||
wizard_form.action = 'change_account'
|
||||
wizard_form.destination_account_id = self.test_currency_account
|
||||
wizard_form.journal_id = self.journal
|
||||
wizard = wizard_form.save()
|
||||
@@ -275,9 +272,8 @@ class TestTransferWizard(AccountTestInvoicingCommon):
|
||||
active_move_lines = self.move_2.mapped('line_ids').filtered(lambda x: x.name in ('test2_9', 'test2_6', 'test2_8'))
|
||||
|
||||
# We use a form to pass the context properly to the depends_context move_line_ids field
|
||||
context = {'active_model': 'account.move.line', 'active_ids': active_move_lines.ids}
|
||||
context = {'active_model': 'account.move.line', 'active_ids': active_move_lines.ids, 'default_action': 'change_account'}
|
||||
with Form(self.env['account.automatic.entry.wizard'].with_context(context)) as wizard_form:
|
||||
wizard_form.action = 'change_account'
|
||||
wizard_form.destination_account_id = self.receivable_account
|
||||
wizard_form.journal_id = self.journal
|
||||
wizard = wizard_form.save()
|
||||
|
||||
@@ -1152,7 +1152,7 @@
|
||||
aria-label="Change Period"
|
||||
class="float-end"
|
||||
attrs="{'invisible': [('account_internal_group', 'not in', ('income', 'expense'))], 'column_invisible': ['|', ('parent.move_type', '=', 'entry'), ('parent.state', '!=', 'posted')]}"
|
||||
context="{'hide_automatic_options': 1, 'default_action': 'change_period'}"/>
|
||||
context="{'default_action': 'change_period'}"/>
|
||||
|
||||
<!-- Others fields -->
|
||||
<field name="tax_line_id" invisible="1"/>
|
||||
@@ -1368,13 +1368,22 @@
|
||||
<field name="context">{'search_default_account_id': [active_id], 'search_default_posted': 1}</field>
|
||||
</record>
|
||||
|
||||
<record id="action_automatic_entry" model="ir.actions.server">
|
||||
<field name="name">Automatic Entries</field>
|
||||
<record id="action_automatic_entry_change_account" model="ir.actions.server">
|
||||
<field name="name">Move to Account</field>
|
||||
<field name="model_id" ref="account.model_account_move_line"/>
|
||||
<field name="groups_id" eval="[(4, ref('account.group_account_user'))]"/>
|
||||
<field name="binding_model_id" ref="account.model_account_move_line"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">action = records.action_automatic_entry()</field>
|
||||
<field name="code">action = records.action_automatic_entry('change_account')</field>
|
||||
</record>
|
||||
|
||||
<record id="action_automatic_entry_change_period" model="ir.actions.server">
|
||||
<field name="name">Change Period</field>
|
||||
<field name="model_id" ref="account.model_account_move_line"/>
|
||||
<field name="groups_id" eval="[(4, ref('account.group_account_user'))]"/>
|
||||
<field name="binding_model_id" ref="account.model_account_move_line"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">action = records.action_automatic_entry('change_period')</field>
|
||||
</record>
|
||||
|
||||
<record id="action_account_moves_all_a" model="ir.actions.act_window">
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="move_line_ids" invisible="1"/>
|
||||
<field name="display_currency_helper" invisible="1"/>
|
||||
<field name="action" invisible="1"/>
|
||||
<div attrs="{'invisible': [('display_currency_helper', '=', False)]}" class="alert alert-info text-center" role="status">
|
||||
The selected destination account is set to use a specific currency. Every entry transferred to it will be converted into this currency, causing
|
||||
the loss of any pre-existing foreign currency amount.
|
||||
</div>
|
||||
<field name="action" invisible="context.get('hide_automatic_options')" widget="radio" options="{'horizontal': true}"/>
|
||||
<group>
|
||||
<group attrs="{'invisible': [('action', '!=', 'change_period')]}">
|
||||
<field name="date" string="Recognition Date"/>
|
||||
@@ -47,7 +47,7 @@
|
||||
</record>
|
||||
|
||||
<record id="account_automatic_entry_wizard_action" model="ir.actions.act_window">
|
||||
<field name="name">Create Automatic Entries for selected Journal Items</field>
|
||||
<field name="name">Transfer Journal Items</field>
|
||||
<field name="res_model">account.automatic.entry.wizard</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
|
||||
Reference in New Issue
Block a user