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 write off if the rule has a "set_partner_id" and the statement
line does not have a partner set. 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. ''' Apply criteria to get candidates for all reconciliation models.
This function is called in enterprise by the reconciliation widget to match 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 st_line: The statement line to match.
:param excluded_ids: Account.move.lines to exclude. :param partner: The partner to consider.
:param partner_map: Dict mapping each line with new partner eventually.
:return: A dict mapping each statement line id with: :return: A dict mapping each statement line id with:
* aml_ids: A list of account.move.line ids. * aml_ids: A list of account.move.line ids.
* model: An account.reconcile.model record (optional). * model: An account.reconcile.model record (optional).
* status: 'reconciled' if the lines has been already reconciled, 'write_off' if the write-off must be * status: 'reconciled' if the lines has been already reconciled, 'write_off' if the write-off
applied on the statement line. 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() 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: 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): if not 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
continue 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: if candidate_vals.get('amls'):
candidates = all_model_candidates[st_line.id] res = rec_model._get_invoice_matching_amls_result(st_line, partner, candidate_vals)
if candidates: if res:
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) return {
**res,
'model': rec_model,
}
else:
return {
**candidate_vals,
'model': rec_model,
}
if model_rslt: elif rec_model.rule_type == 'writeoff_suggestion':
# We inject the selected partner (possibly coming from the rec model) # customize
model_rslt['partner']= partner if rec_model.set_partner_id and not st_line.partner_id:
st_line.partner_id = rec_model.set_partner_id
results[st_line.id] = model_rslt return {
reconciled_amls_ids |= new_reconciled_aml_ids 'model': rec_model,
aml_ids_to_exclude |= new_treated_aml_ids 'status': 'write_off',
matched_lines += st_line 'auto_reconcile': rec_model.auto_reconcile,
}
return results # end customize
return {}

View File

@@ -30,6 +30,13 @@ class OpencartSaleOrder(models.Model):
digits=dp.get_precision('Account') 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 @api.model
def import_batch(self, backend, filters=None): def import_batch(self, backend, filters=None):
""" Prepare the import of Sales Orders from Opencart """ """ Prepare the import of Sales Orders from Opencart """