Skip to content

Commit

Permalink
[REF] edi_upflow: sync partial reconcile instead full reconcile
Browse files Browse the repository at this point in the history
  • Loading branch information
petrus-v committed Feb 6, 2024
1 parent bf99edc commit 0df3b5f
Show file tree
Hide file tree
Showing 18 changed files with 606 additions and 240 deletions.
2 changes: 1 addition & 1 deletion edi_upflow/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ EDI UPFLOW
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:ce4e7b14fcd390046d7027b606b92cb2bb40facfc187402e4b0696b83aac11e4
!! source digest: sha256:00bc337e6cc52b983cc045c3ce3d00bac45a579a40f1c927696738ed7433fa59
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png
Expand Down
3 changes: 2 additions & 1 deletion edi_upflow/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
{
"name": "EDI UPFLOW",
"summary": "Odoo Upflow.io connector",
"version": "14.0.1.1.0",
"version": "14.0.2.0.0",
"development_status": "Alpha",
"category": "EDI",
"website": "https://github.com/OCA/credit-control",
Expand All @@ -24,6 +24,7 @@
"data/cron.xml",
"data/edi.xml",
"views/account_full_reconcile.xml",
"views/account_partial_reconcile.xml",
"views/edi_exchange_record.xml",
"views/res_config_settings.xml",
"views/res_partner.xml",
Expand Down
2 changes: 1 addition & 1 deletion edi_upflow/components/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
edi_output_generate_upflow_post_refunds,
edi_output_generate_upflow_put_contacts,
edi_webservice_send,
event_listener_account_full_reconcile,
event_listener_account_move,
event_listener_account_partial_reconcile,
event_listener_exchange_record,
event_listener_res_partner,
request_adapter,
Expand Down
44 changes: 1 addition & 43 deletions edi_upflow/components/event_listener_account_move.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,46 +17,4 @@ class AccountMoveUpflowEventListener(Component):
_apply_on = ["account.move"]

def on_post_account_move(self, moves):
for move in moves:
exchange_type = None
pdf_exchange = None
if move.move_type == "out_invoice":
exchange_type = "upflow_post_invoice"
pdf_exchange = "upflow_post_invoice_pdf"
elif move.move_type == "out_refund":
exchange_type = "upflow_post_credit_notes"
pdf_exchange = "upflow_post_credit_notes_pdf"
elif move.move_type == "entry" and move.payment_id:
if (
move.payment_id.payment_type == "inbound"
and move.payment_id.partner_type == "customer"
):
exchange_type = "upflow_post_payments"
elif (
move.payment_id.payment_type == "outbound"
and move.payment_id.partner_type == "customer"
):
exchange_type = "upflow_post_refunds"

if not exchange_type:
continue
customer_exchange = self.env["edi.exchange.record"]
backend = move.commercial_partner_id.upflow_edi_backend_id
if not move.commercial_partner_id.upflow_uuid or not backend:
backend = self._get_followup_backend(move)
customer_exchange = self._create_and_generate_upflow_exchange_record(
backend, "upflow_post_customers", move.commercial_partner_id
)
move.commercial_partner_id.upflow_edi_backend_id = backend
account_move_exchange = self._create_and_generate_upflow_exchange_record(
backend, exchange_type, move
)
if not account_move_exchange:
# empty recordset could be return in case no backend found
continue
account_move_exchange.dependent_exchange_ids |= customer_exchange
if pdf_exchange:
pdf_exchange = self._create_and_generate_upflow_exchange_record(
backend, pdf_exchange, move
)
pdf_exchange.dependent_exchange_ids |= account_move_exchange
self.send_moves_to_upflow(moves)
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
logger = logging.getLogger(__name__)


class AccountFullReconcileUpflowEventListener(Component):
class AccountPartialReconcileUpflowEventListener(Component):

_name = "account.full.reconcile.upflow.event.listener"
_name = "account.partial.reconcile.upflow.event.listener"
_inherit = "base.upflow.event.listener"
_apply_on = ["account.full.reconcile"]
_apply_on = ["account.partial.reconcile"]

def _filter_relevant_account_event_state_method(self, states):
"""Only accounting event (ignore pdf events)"""
Expand All @@ -30,7 +30,7 @@ def _filter_relevant_account_event_state_method(self, states):
and ex.edi_exchange_state in states
)

def _ensure_related_move_is_synced(self, reconcile_exchange, move, exchange_type):
def _ensure_related_move_is_synced(self, reconcile_exchange, move):
"output_sent_and_processed"
ongoing_move_exchanges = move.exchange_record_ids.filtered(
self._filter_relevant_account_event_state_method(
Expand All @@ -57,23 +57,15 @@ def _ensure_related_move_is_synced(self, reconcile_exchange, move, exchange_type
ongoing_move_exchanges | finalized_move_exchanges
)
else:
self._create_missing_exchange_record(
reconcile_exchange, move, exchange_type
)
self._create_missing_exchange_record(reconcile_exchange, move)

def _create_missing_exchange_record(self, reconcile_exchange, move, exchange_type):
def _create_missing_exchange_record(self, reconcile_exchange, move):
if move.upflow_commercial_partner_id:
# create payment from bank statements
# do not necessarily generate account.payment

# At this point we expect customer to be already synchronized
exchange = self._create_and_generate_upflow_exchange_record(
move.commercial_partner_id.upflow_edi_backend_id
or self._get_followup_backend(move),
exchange_type,
move,
)
reconcile_exchange.dependent_exchange_ids |= exchange
reconcile_exchange.dependent_exchange_ids |= self.send_moves_to_upflow(move)
else:
raise UserError(
_(
Expand All @@ -88,56 +80,63 @@ def _create_missing_exchange_record(self, reconcile_exchange, move, exchange_typ
)

def _is_customer_entry(self, reconcile):
"""Return true when all moves are linked to receivable lines"""
return all(
[
acc_type.type == "receivable"
for acc_type in reconcile.reconciled_line_ids.account_id.user_type_id
]
# both should share the same type anyway
return (
reconcile.debit_move_id.account_id.user_type_id.type == "receivable"
or reconcile.credit_move_id.account_id.user_type_id.type == "receivable"
)

def _get_reconcile_partner(self, account_partial_reconcile):
"""credit/debit move line should be link to the same partner
and partner_id should be present on receivable account.move.line
Anyway we try to be kind here and find
"""
return (
account_partial_reconcile.debit_move_id.partner_id.commercial_partner_id
or account_partial_reconcile.credit_move_id.partner_id.commercial_partner_id
or account_partial_reconcile.debit_move_id.move_id.commercial_partner_id
or account_partial_reconcile.credit_move_id.move_id.commercial_partner_id
)

def on_record_create(self, account_full_reconcile, fields=None):
if not self._is_customer_entry(account_full_reconcile):
def _get_backend(self, account_partial_reconcile):
partner = self._get_reconcile_partner(account_partial_reconcile)
return partner.upflow_edi_backend_id or self._get_followup_backend(
account_partial_reconcile.debit_move_id.move_id
)

def on_record_create(self, account_partial_reconcile, fields=None):
if not self._is_customer_entry(account_partial_reconcile):
return
first_move = account_full_reconcile.reconciled_line_ids.filtered(
lambda move_line: move_line.move_id.commercial_partner_id
)[0].move_id

reconcile_exchange = self._create_and_generate_upflow_exchange_record(
first_move.commercial_partner_id.upflow_edi_backend_id
or self._get_followup_backend(first_move),
self._get_backend(account_partial_reconcile),
"upflow_post_reconcile",
account_full_reconcile,
account_partial_reconcile,
)
if not reconcile_exchange:
# in case no backend is returned there are nothing to do
return
for partial in account_full_reconcile.partial_reconcile_ids:
self._ensure_related_move_is_synced(
reconcile_exchange,
partial.credit_move_id.move_id,
"upflow_post_payments",
)
self._ensure_related_move_is_synced(
reconcile_exchange, partial.debit_move_id.move_id, "upflow_post_refunds"
)
self._ensure_related_move_is_synced(
reconcile_exchange,
account_partial_reconcile.credit_move_id.move_id,
)
self._ensure_related_move_is_synced(
reconcile_exchange,
account_partial_reconcile.debit_move_id.move_id,
)

def on_record_unlink(self, account_full_reconcile):
if account_full_reconcile.sent_to_upflow:
def on_record_unlink(self, account_partial_reconcile):
if account_partial_reconcile.sent_to_upflow:
# we are not using _create_and_generate_upflow_exchange_record
# here because we want to generate payload synchronously
# after wards record will be unlinked with no chance to retrieves
# upflow_uuid
first_move = account_full_reconcile.reconciled_line_ids.filtered(
lambda move_line: move_line.move_id.commercial_partner_id
)[0].move_id
backend = (
first_move.commercial_partner_id.upflow_edi_backend_id
or self._get_followup_backend(first_move)
)
backend = self._get_backend(account_partial_reconcile)
if backend:
exchange_record = backend.create_record(
"upflow_post_reconcile",
self._get_exchange_record_vals(account_full_reconcile),
self._get_exchange_record_vals(account_partial_reconcile),
)
backend.with_context(unlinking_reconcile=True).exchange_generate(
exchange_record
Expand Down
41 changes: 41 additions & 0 deletions edi_upflow/components/event_listener_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,44 @@ def _create_and_generate_upflow_exchange_record(
else:
return self.env["edi.exchange.record"]
return exchange_record

def send_moves_to_upflow(self, moves):
move_exchanges = self.env["edi.exchange.record"].browse()
# if a lot of things happen in this same transaction probably
# depends are not computed yet better to refresh value
moves._compute_upflow_type()
for move in moves:
exchange_type, pdf_exchange = move.mapping_upflow_exchange().get(
move.upflow_type,
(
None,
None,
),
)

if not exchange_type:
continue
customer_exchange = self.env["edi.exchange.record"]
backend = (
move.upflow_commercial_partner_id.upflow_edi_backend_id
or self._get_followup_backend(move)
)
if not move.upflow_commercial_partner_id.upflow_uuid:
customer_exchange = self._create_and_generate_upflow_exchange_record(
backend, "upflow_post_customers", move.upflow_commercial_partner_id
)
move.upflow_commercial_partner_id.upflow_edi_backend_id = backend
account_move_exchange = self._create_and_generate_upflow_exchange_record(
backend, exchange_type, move
)
if not account_move_exchange:
# empty recordset could be return in case no backend found
continue
account_move_exchange.dependent_exchange_ids |= customer_exchange
if pdf_exchange:
pdf_exchange = self._create_and_generate_upflow_exchange_record(
backend, pdf_exchange, move
)
pdf_exchange.dependent_exchange_ids |= account_move_exchange
move_exchanges |= account_move_exchange
return move_exchanges
Loading

0 comments on commit 0df3b5f

Please sign in to comment.