feat: track electronic payment reporting status
This commit is contained in:
@@ -7,7 +7,7 @@ from typing import Any
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import flt
|
||||
from frappe.utils import flt, now_datetime
|
||||
|
||||
from enuxia_einvoice.inbound_sync import (
|
||||
_acquire_nonblocking_lock,
|
||||
@@ -114,10 +114,7 @@ def _find_payment_received_event(
|
||||
event.get("status_code") or ""
|
||||
).strip()
|
||||
|
||||
if (
|
||||
status_code
|
||||
== PAYMENT_RECEIVED_STATUS
|
||||
):
|
||||
if status_code == PAYMENT_RECEIVED_STATUS:
|
||||
return event
|
||||
|
||||
return None
|
||||
@@ -143,6 +140,65 @@ def _payment_lock_name(
|
||||
)
|
||||
|
||||
|
||||
def _set_payment_tracking(
|
||||
invoice,
|
||||
*,
|
||||
status: str,
|
||||
event_id: Any = None,
|
||||
error: str = "",
|
||||
) -> None:
|
||||
"""Mettre à jour le suivi d'encaissement de la facture."""
|
||||
|
||||
values: dict[str, Any] = {
|
||||
"einvoice_payment_status": status,
|
||||
"einvoice_payment_last_error": str(
|
||||
error or ""
|
||||
)[:1000],
|
||||
}
|
||||
|
||||
if status == "Reported":
|
||||
values.update(
|
||||
{
|
||||
"einvoice_payment_reported_at": (
|
||||
now_datetime()
|
||||
),
|
||||
"einvoice_payment_event_id": (
|
||||
str(event_id)
|
||||
if event_id is not None
|
||||
else ""
|
||||
),
|
||||
"einvoice_payment_last_error": "",
|
||||
}
|
||||
)
|
||||
|
||||
invoice.db_set(
|
||||
values,
|
||||
update_modified=True,
|
||||
)
|
||||
|
||||
|
||||
def _synchronize_after_payment(
|
||||
invoice_name: str,
|
||||
) -> tuple[dict[str, Any], list[str]]:
|
||||
"""Synchroniser sans annuler un événement déjà créé."""
|
||||
|
||||
try:
|
||||
result = sync_sales_invoice_status(
|
||||
invoice_name
|
||||
)
|
||||
|
||||
return result, []
|
||||
|
||||
except Exception as exc:
|
||||
warning = _(
|
||||
"L'encaissement a bien été déclaré, "
|
||||
"mais la synchronisation complète du statut "
|
||||
"a échoué : {0}"
|
||||
).format(str(exc))
|
||||
|
||||
return {}, [warning]
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def report_payment_received(
|
||||
invoice_name: str,
|
||||
@@ -185,6 +241,17 @@ def report_payment_received(
|
||||
)
|
||||
|
||||
try:
|
||||
if (
|
||||
invoice.get(
|
||||
"einvoice_payment_status"
|
||||
)
|
||||
!= "Reported"
|
||||
):
|
||||
_set_payment_tracking(
|
||||
invoice,
|
||||
status="To Report",
|
||||
)
|
||||
|
||||
client, access_token = (
|
||||
get_authenticated_client(
|
||||
invoice.company
|
||||
@@ -211,8 +278,16 @@ def report_payment_received(
|
||||
events_payload,
|
||||
)
|
||||
|
||||
sync_result = (
|
||||
sync_sales_invoice_status(
|
||||
event_id = existing_event.get("id")
|
||||
|
||||
_set_payment_tracking(
|
||||
invoice,
|
||||
status="Reported",
|
||||
event_id=event_id,
|
||||
)
|
||||
|
||||
sync_result, warnings = (
|
||||
_synchronize_after_payment(
|
||||
invoice.name
|
||||
)
|
||||
)
|
||||
@@ -227,14 +302,15 @@ def report_payment_received(
|
||||
"provider_status": (
|
||||
PAYMENT_RECEIVED_STATUS
|
||||
),
|
||||
"event_id": existing_event.get(
|
||||
"id"
|
||||
),
|
||||
"payment_status": "Reported",
|
||||
"event_id": event_id,
|
||||
"latest_event": (
|
||||
sync_result.get(
|
||||
"latest_event"
|
||||
)
|
||||
or existing_event
|
||||
),
|
||||
"warnings": warnings,
|
||||
"message": _(
|
||||
"L'encaissement avait déjà été "
|
||||
"déclaré auprès de SuperPDP."
|
||||
@@ -251,8 +327,16 @@ def report_payment_received(
|
||||
)
|
||||
)
|
||||
|
||||
sync_result = (
|
||||
sync_sales_invoice_status(
|
||||
event_id = created_event.get("id")
|
||||
|
||||
_set_payment_tracking(
|
||||
invoice,
|
||||
status="Reported",
|
||||
event_id=event_id,
|
||||
)
|
||||
|
||||
sync_result, warnings = (
|
||||
_synchronize_after_payment(
|
||||
invoice.name
|
||||
)
|
||||
)
|
||||
@@ -267,19 +351,35 @@ def report_payment_received(
|
||||
"provider_status": (
|
||||
PAYMENT_RECEIVED_STATUS
|
||||
),
|
||||
"event_id": created_event.get(
|
||||
"id"
|
||||
),
|
||||
"payment_status": "Reported",
|
||||
"event_id": event_id,
|
||||
"latest_event": (
|
||||
sync_result.get(
|
||||
"latest_event"
|
||||
)
|
||||
or created_event
|
||||
),
|
||||
"warnings": warnings,
|
||||
"message": _(
|
||||
"L'encaissement a été déclaré "
|
||||
"auprès de SuperPDP."
|
||||
),
|
||||
}
|
||||
|
||||
except Exception as exc:
|
||||
if (
|
||||
invoice.get(
|
||||
"einvoice_payment_status"
|
||||
)
|
||||
!= "Reported"
|
||||
):
|
||||
_set_payment_tracking(
|
||||
invoice,
|
||||
status="Error",
|
||||
error=str(exc),
|
||||
)
|
||||
|
||||
raise
|
||||
|
||||
finally:
|
||||
_release_lock(lock)
|
||||
|
||||
@@ -238,11 +238,59 @@ CUSTOM_FIELDS = {
|
||||
"insert_after": "einvoice_last_validation",
|
||||
"read_only": 1,
|
||||
},
|
||||
{
|
||||
"fieldname": "einvoice_payment_section",
|
||||
"label": "Suivi de l’encaissement",
|
||||
"fieldtype": "Section Break",
|
||||
"insert_after": "einvoice_last_sync",
|
||||
"collapsible": 1,
|
||||
},
|
||||
{
|
||||
"fieldname": "einvoice_payment_status",
|
||||
"label": "Statut de l’encaissement électronique",
|
||||
"fieldtype": "Select",
|
||||
"insert_after": "einvoice_payment_section",
|
||||
"options": (
|
||||
"Not Applicable\n"
|
||||
"Waiting for Payment\n"
|
||||
"To Report\n"
|
||||
"Reported\n"
|
||||
"Error"
|
||||
),
|
||||
"default": "Not Applicable",
|
||||
"read_only": 1,
|
||||
"allow_on_submit": 1,
|
||||
"in_standard_filter": 1,
|
||||
},
|
||||
{
|
||||
"fieldname": "einvoice_payment_reported_at",
|
||||
"label": "Encaissement déclaré le",
|
||||
"fieldtype": "Datetime",
|
||||
"insert_after": "einvoice_payment_status",
|
||||
"read_only": 1,
|
||||
"allow_on_submit": 1,
|
||||
},
|
||||
{
|
||||
"fieldname": "einvoice_payment_event_id",
|
||||
"label": "Identifiant de l’événement de paiement",
|
||||
"fieldtype": "Data",
|
||||
"insert_after": "einvoice_payment_reported_at",
|
||||
"read_only": 1,
|
||||
"allow_on_submit": 1,
|
||||
},
|
||||
{
|
||||
"fieldname": "einvoice_payment_last_error",
|
||||
"label": "Erreur de déclaration de l’encaissement",
|
||||
"fieldtype": "Small Text",
|
||||
"insert_after": "einvoice_payment_event_id",
|
||||
"read_only": 1,
|
||||
"allow_on_submit": 1,
|
||||
},
|
||||
{
|
||||
"fieldname": "einvoice_diagnostics_section",
|
||||
"label": "Diagnostic",
|
||||
"fieldtype": "Section Break",
|
||||
"insert_after": "einvoice_last_sync",
|
||||
"insert_after": "einvoice_payment_last_error",
|
||||
"collapsible": 1,
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
from datetime import datetime
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from enuxia_einvoice.payment_reporting import (
|
||||
@@ -20,6 +21,21 @@ class TestPaymentReporting(unittest.TestCase):
|
||||
translation_patcher.start()
|
||||
self.addCleanup(translation_patcher.stop)
|
||||
|
||||
datetime_patcher = patch(
|
||||
"enuxia_einvoice.payment_reporting."
|
||||
"now_datetime",
|
||||
return_value=datetime(
|
||||
2026,
|
||||
6,
|
||||
21,
|
||||
12,
|
||||
0,
|
||||
0,
|
||||
),
|
||||
)
|
||||
datetime_patcher.start()
|
||||
self.addCleanup(datetime_patcher.stop)
|
||||
|
||||
def invoice(
|
||||
self,
|
||||
*,
|
||||
|
||||
Reference in New Issue
Block a user