cpro-client 0.2.4 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eed2218b6135210909bb231938a2adf3d8f9b432a19468576b232ffd2f352d7a
4
- data.tar.gz: 95739510c05be2fdc248b2f001e4b53e08b3487162dbb29f50bc26606d929e06
3
+ metadata.gz: fcf97fbee94114c1241fb76a3b3ec620dd7d8c2e40435bebfe146ce7b65a3e92
4
+ data.tar.gz: 0b3e4f80fe36110c60a46d7adc951cb0bd662093a30e39a0f19fb9e4c252096d
5
5
  SHA512:
6
- metadata.gz: 7208819c95be0220d40498c3d09c5df5479619c652c6103aac41903ce1cac6054f47b53a7c87638fd7b474e99581a61b6924ab1d0f17b633bb18a72d431e8a94
7
- data.tar.gz: 4c292e8c13863bdff0fe54ab567e42880c4d25e5d928ca70fb6c1a83284198912cc14b5dd787f0733763e181a7923f08ab7768a0ee5007b5b4e52b3719c4b7f0
6
+ metadata.gz: 4f010893e86d5f3dec2742aca27ea56606f6facb294c23cc613f91073d4ebf3b3f56dc1fdea650121b76a706680a65bd4921c875230a0e00beb428d4306f7876
7
+ data.tar.gz: 65724ca9625aa0328e6d3b14f10005f087614e589587f73e706b17d515b1091f3633f960bf9036a8031e30abdab360814856d076de551eaa0f5a860759b3a0a9
data/CHANGELOG.md CHANGED
@@ -1,6 +1,30 @@
1
1
  ## [Unreleased]
2
2
 
3
3
 
4
+ ## [0.2.5] - 2026-09-05
5
+
6
+ ### Ajouté
7
+ - `Cpro::Client#suivi` enchaîne les appels de suivi d'un dépôt — statut du flux, recherche de la
8
+ facture, consultation avec son historique — et rend un `Cpro::Suivi` qui nomme l'étape atteinte :
9
+ `:flux_en_attente` (404 du PPF, cas nominal juste après un dépôt), `:flux_irrecevable`,
10
+ `:facture_introuvable` (204, ambigu par nature) ou `:facture_connue`. Il court-circuite dès
11
+ qu'un palier interdit d'aller plus loin : un appel tant que le flux n'est pas traité, trois au
12
+ plus. Il n'attend jamais — la cadence d'interrogation appartient à l'appelant — et laisse
13
+ `statut_flux` et `facture` accessibles pour ce qu'il n'interprète pas.
14
+ - `Cpro::Entities::Facture#dernier_incident`, relayé par `Cpro::Suivi#dernier_incident`, isole le
15
+ dernier changement de statut porteur de motifs — l'incident en cours — là où `motifs_rejet`
16
+ cumule tout l'historique. Il rend le changement et non le motif : un même changement en porte
17
+ plusieurs, une facture « Déposée » pouvant cumuler `NON_TRANSMISE` et `REJ_UNI`.
18
+ - `Cpro::Suivi#motifs` rassemble les motifs de rejet, qu'ils viennent du flux ou de l'historique de
19
+ la facture : l'appelant n'a plus à savoir où le dépôt s'est arrêté pour aller les chercher.
20
+ - `Cpro::Entities::Facture#en_echec?` — vrai dès qu'une facture demande une intervention, que son
21
+ statut l'annonce ou non. Chorus Pro accroche ses motifs de rejet au statut porteur, qui peut
22
+ être anodin : une facture « Déposée » assortie de `NON_TRANSMISE` ne parviendra pas à son
23
+ destinataire alors que `rejetee?` répond faux. Le prédicat couvre les statuts `REJETEE` et
24
+ `ERREUR_ROUTAGE` ainsi que tout motif présent dans l'historique — lequel n'est renseigné que
25
+ par `Factures#find`.
26
+
27
+
4
28
  ## [0.2.3] - 2026-08-31
5
29
 
6
30
  ### Ajouté
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cpro-client (0.2.4)
4
+ cpro-client (0.2.5)
5
5
  faraday (>= 0.9, < 3.0)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -254,6 +254,48 @@ aucune facture ne correspond que lorsque le compte technique n'est rattaché ni
254
254
  callback, et les statuts des factures G2B ne sont pas consultables sur le portail Chorus Pro : le
255
255
  suivi passe nécessairement par une interrogation périodique de cette API.
256
256
 
257
+ ## Suivre un dépôt en un appel
258
+
259
+ Les quatre étapes du suivi — statut du flux, recherche par `nomFlux`, consultation, lecture des
260
+ motifs — se réduisent à une méthode, qui nomme l'étape atteinte plutôt que de lever ou de rendre
261
+ `nil` :
262
+
263
+ ```ruby
264
+ suivi = client.suivi(depot)
265
+
266
+ suivi.etape # :flux_en_attente, :flux_irrecevable, :facture_introuvable, :facture_connue
267
+ suivi.en_echec? # au niveau de l'enveloppe comme à celui de la facture
268
+ suivi.motifs # les motifs, d'où qu'ils viennent
269
+ suivi.facture # la facture et son historique, à l'étape :facture_connue
270
+ suivi.statut_flux # le statut brut du flux, dès qu'il est connu
271
+ ```
272
+
273
+ `motifs` cumule tout l'historique — un incident réglé y côtoie l'incident courant. Pour n'avoir que
274
+ le plus récent, avec le statut qui le portait et sa date :
275
+
276
+ ```ruby
277
+ incident = suivi.dernier_incident # un ChangementStatut, ou nil
278
+
279
+ incident.statut # "DEPOSEE"
280
+ incident.date # 2026-09-04 19:18:31 UTC
281
+ incident.motifs_rejet.map(&:code) # ["NON_TRANSMISE", "REJ_UNI"]
282
+ ```
283
+
284
+ Il rend le changement et non le motif : un même changement en porte plusieurs, et n'en exposer
285
+ qu'un les masquerait. Il vaut `nil` à l'étape `:flux_irrecevable`, où il n'y a pas encore de
286
+ facture — `motifs` reste alors l'accès uniforme.
287
+
288
+ | Étape | Ce qui s'est passé | Appels | Suite |
289
+ | --- | --- | :-: | --- |
290
+ | `:flux_en_attente` | 404 sur le flux — cas nominal | 1 | réinterroger |
291
+ | `:flux_irrecevable` | enveloppe refusée, motifs sur le flux | 1 | terminal |
292
+ | `:facture_introuvable` | flux recevable, recherche vide | 2 | réinterroger, puis vérifier le rattachement du compte |
293
+ | `:facture_connue` | facture et historique disponibles | 3 | lire `en_echec?` et les motifs |
294
+
295
+ La méthode **n'attend pas** : c'est une photographie, la cadence d'interrogation reste à l'appelant.
296
+ Seuls le 404 du flux et la recherche vide deviennent des étapes ; un 401, un 403 ou un 5xx
297
+ continuent de lever.
298
+
257
299
  ## Servir plusieurs entités
258
300
 
259
301
  L'AIFE distingue trois types de raccordement API. Celui qui s'applique détermine le modèle à
data/lib/cpro/client.rb CHANGED
@@ -19,6 +19,12 @@ module Cpro
19
19
  self.class.new(configuration, account: account, token_provider: token_provider, connections: connections)
20
20
  end
21
21
 
22
+ # Enchaîne les appels de suivi d'un dépôt et rend une synthèse. Traverse deux ressources,
23
+ # d'où sa place ici plutôt que sur l'une d'elles.
24
+ def suivi(depot)
25
+ Suivi.pour(self, depot)
26
+ end
27
+
22
28
  def annuaire
23
29
  @annuaire ||= Resources::Annuaire.new(self, connection_for(ANNUAIRE_PATH))
24
30
  end
@@ -10,6 +10,11 @@ module Cpro
10
10
  CHANGEMENT_DE_COMPTE_A_PAYER NON_AFFACTUREE AFFACTUREE AFFACTUREE_CONFIDENTIEL
11
11
  ].freeze
12
12
 
13
+ EPOQUE = Time.at(0).utc
14
+
15
+ # Statuts qui constatent par eux-mêmes qu'une facture n'arrivera pas.
16
+ STATUTS_EN_ECHEC = %w[REJETEE ERREUR_ROUTAGE].freeze
17
+
13
18
  CHAMPS = {
14
19
  uid: "uidFacture",
15
20
  numero: "numeroFacture",
@@ -77,6 +82,36 @@ module Cpro
77
82
  historique.flat_map(&:motifs_rejet)
78
83
  end
79
84
 
85
+ # Le dernier changement de statut porteur de motifs — celui qui décrit l'incident en cours,
86
+ # là où `motifs_rejet` cumule tout l'historique, motifs devenus caducs compris.
87
+ #
88
+ # Rend le changement et non le motif : un même changement en porte plusieurs — une facture
89
+ # « Déposée » peut cumuler NON_TRANSMISE et REJ_UNI — et n'en exposer qu'un les masquerait.
90
+ # Le rang départage deux changements de même date, le plus récent l'emportant.
91
+ def dernier_incident
92
+ incidents = historique.select(&:rejet?)
93
+ incidents.each_with_index.max_by { |changement, rang| [changement.date || EPOQUE, rang] }&.first
94
+ end
95
+
96
+ # Vrai dès qu'une facture demande une intervention, que son statut l'annonce ou non : un
97
+ # motif de rejet peut être porté par un statut anodin. Une facture « Déposée » accompagnée
98
+ # de NON_TRANSMISE en est le cas type — `rejetee?` répond faux, et pourtant le destinataire
99
+ # ne la recevra pas par la plateforme.
100
+ #
101
+ # Attention au mot « échec » : NON_TRANSMISE n'invalide pas la facture. Le dossier de
102
+ # spécifications externes est explicite — ce statut « permet à l'entité publique de
103
+ # justifier qu'elle a bien émis une facture électronique et qu'elle a donc respecté ses
104
+ # obligations réglementaires ». Il n'y a donc rien à redéposer ; il y a à livrer autrement.
105
+ #
106
+ # Le refus de l'acheteur (REFUSEE) n'en fait pas partie : c'est une décision métier, une
107
+ # étape normale du cycle de vie, pas un incident. Elle se lit par `refusee?`.
108
+ #
109
+ # L'historique n'étant renseigné que par `Factures#find`, une facture issue d'une recherche
110
+ # ne peut être jugée que sur son statut.
111
+ def en_echec?
112
+ STATUTS_EN_ECHEC.include?(statut) || historique.any?(&:rejet?)
113
+ end
114
+
80
115
  def to_s
81
116
  [numero, statut].compact.join(" ")
82
117
  end
data/lib/cpro/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cpro
4
- VERSION = "0.2.4"
4
+ VERSION = "0.2.5"
5
5
  end
data/lib/cpro.rb CHANGED
@@ -35,6 +35,7 @@ require_relative "cpro/resources/base"
35
35
  require_relative "cpro/resources/annuaire"
36
36
  require_relative "cpro/resources/flux"
37
37
  require_relative "cpro/resources/factures"
38
+ require_relative "cpro/suivi"
38
39
  require_relative "cpro/client"
39
40
 
40
41
  module Cpro
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cpro-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hôtentic
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-09-04 00:00:00.000000000 Z
11
+ date: 2026-09-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday