Project

General

Profile

Bug #55793

Caluire Axel : crash lingo

Added by Nicolas Roche 2 months ago. Updated about 2 months ago.

Status:
Solution déployée
Priority:
Normal
Assignee:
Target version:
-
Start date:
23 Jul 2021
Due date:
% Done:

0%

Estimated time:
Patch proposed:
Yes
Planning:
No

Description

Traceback:

File "/usr/lib/python3/dist-packages/passerelle/utils/jsonresponse.py" in api
  128.             resp = f(*args, **kwargs)

File "/usr/lib/python3/dist-packages/passerelle/views.py" in perform
  527.         result = self.endpoint(request, **params)

File "/usr/lib/python3/dist-packages/passerelle/contrib/caluire_axel/models.py" in pay_invoice
  1220.         code = result.json_response['DATA']['PORTAIL']['SETPAIEMENT']['CODE']

Exception Type: TypeError at /caluire-axel/axel/regie/ENF/invoice/16526-319992/pay/
Exception Value: 'NoneType' object is not subscriptable

Files


Related issues

Related to Combo - Development #55876: lingo : créer le BasketItem représentant le paiement d'une facture quand elle est payée, pas quand l'application est notifiéeSolution déployée27 Jul 2021

Actions

Associated revisions

Revision b7059464 (diff)
Added by Nicolas Roche 2 months ago

caluire-axel: handle wrong messages on pay_invoice (#55793)

History

#1

Updated by Nicolas Roche 2 months ago

Dans les logs du connecteur, l'erreur indique (dans le payload) un numéro de transaction :

body     b'{"transaction_id": "bbd90fe0-eb83-11eb-bb4a-0213ad91a103", "transaction_date": "2021-07-23T07:02:11"}'
method     POST
exception     'NoneType' object is not subscriptable

#2

Updated by Nicolas Roche 2 months ago

La facture concernée :

{
   "data" : {
      "amount" : "2.6",
      "amount_paid" : "0",
      "created" : "2020-02-10",
      "display_id" : "319992",
      "has_pdf" : true,
      "id" : "16526-319992",
      "label" : "Facture unique - Janvier 2020",
      "online_payment" : true,
      "paid" : false,
      "pay_limit_date" : "2020-02-28",
      "total_amount" : "2.6",
      "vendor" : {
         "caluire-axel" : {
            "ECHEANCE" : "2020-02-28",
            "EMISSION" : "2020-02-10",
            "ENCAISSE" : "0",
            "EXISTEPDF" : true,
            "FACTURATION" : "Facture unique - Janvier 2020",
            "IDFACTURE" : 319992,
            "MONTANT" : "2.6" 
         }
      }
   },
   "err" : 0
}

#4

Updated by Nicolas Roche 2 months ago

Axel, qui nous présente cette facture à payer (via GETFACTURESAPAYER), nous renvoie un contenu vide (<PORTAIL/>).
Partant principe que le statut de la réponse est OK (<STATUS>OK</STATUS>) ce contenu aurait du se conformer au schéma R_SetPaiement.xsd et retourner code (0 Ok Négatif sinon dixit la doc).

<?xml version="1.0" encoding="UTF-8"?>
<PORTAILSERVICE>
  <RESULTAT>
    <TYPE>SetPaiement</TYPE>
    <STATUS>OK</STATUS>
    <DATE>23/07/2021 15:44:17</DATE>
    <COMMENTAIRES><![CDATA[]]></COMMENTAIRES>
  </RESULTAT>
  <DATA>
    <PORTAIL/>
  </DATA>
</PORTAILSERVICE>

#5

Updated by Nicolas Roche 2 months ago

  • Status changed from Nouveau to Fermé

Je ferme ici car la cause première est qu'il s'agit d'une facture payée après sa date d'échéance
(Il n'y a pas d'erreur dans le code du connecteur).

Il restera néanmoins à corriger les données sur l'instance calluire (ticket projet).

#7

Updated by Benjamin Dauvergne 2 months ago

  • Status changed from Fermé to Nouveau

Bah si y a un bug dans le connecteur. Au minimum il ne faudrait pas tracer, si Axel peut retourner un truc, vide il faut le détecter et retourner un message d'erreur "facture qui n'existe plus/payée hors échéance" et aussi pourquoi cette facture a pu être payée si elle est hors échéance ? Elle n'aurait jamais du être retournée (ou alors c'est un cas limite payé au moment de la limite et donc ma première réponse est bonne faut une erreur claire sur le problème et dans le workflow passer en mode "récupération manuelle cas paiement hors date limite").

#8

Updated by Benjamin Dauvergne 2 months ago

Il faut mettre online_payment à False ou alors ne pas retourner la facture hors historique.

#9

Updated by Nicolas Roche 2 months ago

Il faut mettre online_payment à False

Désolé, je ne comprend pas.
Je reformule : Axel dit voilà ce qu'il faut payer, Lingo lui dit "voilà c'est fait" et Axel qui devrait dire "ok" ou "erreur" renvoie un message non conforme aux specs.

On est sur un crach du endpoit /caluire-axel/axel/regie/ENF/invoice/16526-319992/pay/
qui est appelé par lingo sans qu'ensuite aucune attention ne soit acordée contenu retourné.

regie.pay_invoice(item_id, self.order_id, self.bank_transaction_date or self.end_date)

Si l'on ne crash pas, alors l'appel ne sera plus retenté et la transaction ne sera plus vue comme orpheline (au sens de la note #3) alors que l'on ne sait pas si elle a bien été prise en compte ou non par le logiciel métier.

edit:
Désolé j'ai été embrouillé par https://dev.entrouvert.org/issues/55793#note-8 qui a plutôt rapport avec #55803.
Et donc oui, renvoyer une erreur qui donne du contexte plutôt que de crasher.

#10

Updated by Nicolas Roche 2 months ago

#11

Updated by Frédéric Péters 2 months ago

Je taperais plus large, façon

-        code = result.json_response['DATA']['PORTAIL']['SETPAIEMENT']['CODE']
+        try:
+            code = int(result.json_response['DATA']['PORTAIL']['SETPAIEMENT']['CODE'])
+        except (KeyError, ValueError):
+            raise APIError('Wrong pay-invoice response', err_code='pay-invoice-code-response-error')
+
         if code < 0:
             raise APIError('Wrong pay-invoice status', err_code='pay-invoice-code-error-%s' % code)

(de ton patch il y a aussi l'ajout d'une partie "data" à l'erreur, sur ce moment particulier, mais pas sur l'APIError qui peut être levée trois lignes plus bas, je n'ai pas repris ça dans mon exemple).

#13

Updated by Thomas Noël (congés → 11 octobre) 2 months ago

Oui pour ajouter du data pour avoir le contexte dans l'APIError, mais que va-t-il devenir (où va-t-on pouvoir le voir afin de comprendre la panne) ?

Par ailleurs sur le premier data, j'ajouterais "post_data": post_data, et j'appelerais kwargs avec son vrai nom "kwargs": kwargs au lieu de payload, qui pourrait laisser croire que c'est ce qu'on a envoyé à Axel.

Dans le second data, j'ajouterais "result": result.json_response pour voir ce qui ne va pas dedans

#19

Updated by Nicolas Roche 2 months ago

Nicolas tu peux creuser le chemin que prend l'ApiError...

Je dirais que si on sort en 500 on l'aura encore dans les traces envoyées par mail.

Pour moi il faudrait qu'on ne soit pas alerté en cas de crash
complet de Axel (lingo retentera chaque heure) mais qu'on le soit en
cas d'erreur incohérente (le second ApiError).

J'ai mis un code 500 sur la deuxième exception

Et que dans les deux cas, ça soit visible dans les journaux de transaction de lingo.

c'est bien prévu :

# 5xx, err or requests error
to_be_paid_remote_items.append(item_id)
logger.warning(
    'unable to notify payment for remote item %s from transaction %s, retry later',
    item_id,
    self,
)

$ ssh grandlyon-guichet-prod-1
$ sudo journalctl TENANT="ville-caluire.toodego.com" | grep 'unable to notify payment'
juil. 27 08:20:36 eddv-gdlyon-gnm-front-1.synaaps.local /usr/lib/combo/manage.py[19282]: combo WARNING ville-caluire.toodego.com - - - unable to notify payment for remote item 16526-319992 from transaction Transaction object (92), retry later

Quand à la résolution du paiement, je doute qu'Axel nous renvoie une réponse un jour
(ici https://dev.entrouvert.org/issues/55799#note-2 on voit qu'Axel ne veut pas accépter l'information comme quoi la facture a été payée).
Pourtant, puisque la facture a bien été payée en ligne, je pense qu'il faut la rattacher à la main à la transaction pour qu'elle apparaisse en visuel ici :
https://ville-caluire.toodego.com/manage/lingo/?q=bbd90fe0-eb83-11eb-bb4a-0213ad91a103

#20

Updated by Benjamin Dauvergne 2 months ago

Nicolas Roche a écrit :

Pourtant, puisque la facture a bien été payée en ligne, je pense qu'il faut la rattacher à la main à la transaction pour qu'elle apparaisse en visuel ici :
https://ville-caluire.toodego.com/manage/lingo/?q=bbd90fe0-eb83-11eb-bb4a-0213ad91a103

Oui ça c'est un souci lingo, on ne crée le BasketItem lié à une facture que lorsque sont paiement a été notifié1, on devrait le créer dès le retour de la banque, qu'on arrive pas à notifier l'application métier ça ne concerne pas l'usager.

Je viens de créer #55876 sur le sujet.

#21

Updated by Nicolas Roche 2 months ago

Je déporte la création du BasketItem manquant lié à cette facture dans #55877.
Et ici, je re-dépose le même patch, mais qui ne mange pas de ligne.

#22

Updated by Benjamin Dauvergne 2 months ago

  • Status changed from Solution proposée to Solution validée
#23

Updated by Nicolas Roche 2 months ago

  • Status changed from Solution validée to Résolu (à déployer)
commit b70594644a262182b667139dfbc285b4f6dc4a22
Author: Nicolas ROCHE <nroche@entrouvert.com>
Date:   Fri Jul 23 18:45:12 2021 +0200

    caluire-axel: handle wrong messages on pay_invoice (#55793)
#24

Updated by Benjamin Dauvergne 2 months ago

  • Related to Development #55876: lingo : créer le BasketItem représentant le paiement d'une facture quand elle est payée, pas quand l'application est notifiée added
#25

Updated by Frédéric Péters about 2 months ago

  • Status changed from Résolu (à déployer) to Solution déployée

Also available in: Atom PDF