Merge branch '16.0' into 16.0-test

This commit is contained in:
Jared Kipe
2024-03-19 20:25:54 +00:00
2 changed files with 48 additions and 63 deletions

View File

@@ -13,79 +13,57 @@ class AccountReconcileModel(models.Model):
write off if the rule has a "set_partner_id" and the statement
line does not have a partner set.
"""
def _apply_rules(self, st_lines, excluded_ids=None, partner_map=None):
def _apply_rules(self, st_line, partner):
''' Apply criteria to get candidates for all reconciliation models.
This function is called in enterprise by the reconciliation widget to match
the statement lines with the available candidates (using the reconciliation models).
the statement line with the available candidates (using the reconciliation models).
:param st_lines: Account.bank.statement.lines recordset.
:param excluded_ids: Account.move.lines to exclude.
:param partner_map: Dict mapping each line with new partner eventually.
:param st_line: The statement line to match.
:param partner: The partner to consider.
:return: A dict mapping each statement line id with:
* aml_ids: A list of account.move.line ids.
* model: An account.reconcile.model record (optional).
* status: 'reconciled' if the lines has been already reconciled, 'write_off' if the write-off must be
applied on the statement line.
* status: 'reconciled' if the lines has been already reconciled, 'write_off' if the write-off
must be applied on the statement line.
* auto_reconcile: A flag indicating if the match is enough significant to auto reconcile the candidates.
'''
# This functions uses SQL to compute its results. We need to flush before doing anything more.
for model_name in ('account.bank.statement', 'account.bank.statement.line', 'account.move', 'account.move.line', 'res.company', 'account.journal', 'account.account'):
self.env[model_name].flush(self.env[model_name]._fields)
results = {line.id: {'aml_ids': []} for line in st_lines}
available_models = self.filtered(lambda m: m.rule_type != 'writeoff_button').sorted()
aml_ids_to_exclude = set() # Keep track of already processed amls.
reconciled_amls_ids = set() # Keep track of already reconciled amls.
# First associate with each rec models all the statement lines for which it is applicable
lines_with_partner_per_model = defaultdict(lambda: [])
for st_line in st_lines:
# Statement lines created in old versions could have a residual amount of zero. In that case, don't try to
# match anything.
if not st_line.amount_residual:
continue
mapped_partner = (partner_map and partner_map.get(st_line.id) and self.env['res.partner'].browse(partner_map[st_line.id])) or st_line.partner_id
for rec_model in available_models:
partner = mapped_partner or rec_model._get_partner_from_mapping(st_line)
if rec_model._is_applicable_for(st_line, partner):
# Customization
if not partner and rec_model.set_partner_id and not rec_model.match_partner:
partner = rec_model.set_partner_id
st_line.partner_id = partner
# End Customization
lines_with_partner_per_model[rec_model].append((st_line, partner))
# Execute only one SQL query for each model (for performance)
matched_lines = self.env['account.bank.statement.line']
for rec_model in available_models:
# We filter the lines for this model, in case a previous one has already found something for them
filtered_st_lines_with_partner = [x for x in lines_with_partner_per_model[rec_model] if x[0] not in matched_lines]
if not filtered_st_lines_with_partner:
# No unreconciled statement line for this model
if not rec_model._is_applicable_for(st_line, partner):
continue
all_model_candidates = rec_model._get_candidates(filtered_st_lines_with_partner, excluded_ids)
if rec_model.rule_type == 'invoice_matching':
rules_map = rec_model._get_invoice_matching_rules_map()
for rule_index in sorted(rules_map.keys()):
for rule_method in rules_map[rule_index]:
candidate_vals = rule_method(st_line, partner)
if not candidate_vals:
continue
for st_line, partner in filtered_st_lines_with_partner:
candidates = all_model_candidates[st_line.id]
if candidates:
model_rslt, new_reconciled_aml_ids, new_treated_aml_ids = rec_model._get_rule_result(st_line, candidates, aml_ids_to_exclude, reconciled_amls_ids, partner)
if candidate_vals.get('amls'):
res = rec_model._get_invoice_matching_amls_result(st_line, partner, candidate_vals)
if res:
return {
**res,
'model': rec_model,
}
else:
return {
**candidate_vals,
'model': rec_model,
}
if model_rslt:
# We inject the selected partner (possibly coming from the rec model)
model_rslt['partner']= partner
results[st_line.id] = model_rslt
reconciled_amls_ids |= new_reconciled_aml_ids
aml_ids_to_exclude |= new_treated_aml_ids
matched_lines += st_line
return results
elif rec_model.rule_type == 'writeoff_suggestion':
# customize
if rec_model.set_partner_id and not st_line.partner_id:
st_line.partner_id = rec_model.set_partner_id
return {
'model': rec_model,
'status': 'write_off',
'auto_reconcile': rec_model.auto_reconcile,
}
# end customize
return {}

View File

@@ -30,6 +30,13 @@ class OpencartSaleOrder(models.Model):
digits=dp.get_precision('Account')
)
@api.model
def create(self, values):
res = super().create(values)
# this is unfortunate, but the initial fiscal position gets set incorrectly
res.odoo_id._compute_fiscal_position_id()
return res
@api.model
def import_batch(self, backend, filters=None):
""" Prepare the import of Sales Orders from Opencart """