factpulse 2.0.9 → 2.0.11

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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +3 -3
  3. data/Gemfile.lock +1 -1
  4. data/README.md +119 -73
  5. data/docs/ChorusProApi.md +1 -1
  6. data/docs/{FactureEnrichieInfoOutput.md → FactureEnrichieInfo.md} +2 -2
  7. data/docs/LigneDePoste.md +6 -6
  8. data/docs/LigneDePosteMontantRemiseHt.md +15 -0
  9. data/docs/LigneDePosteTauxTvaManuel.md +15 -0
  10. data/docs/LigneDeTVA.md +6 -6
  11. data/docs/{MontantHtTotal1.md → MontantAPayer.md} +2 -2
  12. data/docs/{MontantTtcTotal1.md → MontantBaseHt.md} +2 -2
  13. data/docs/MontantRemiseGlobaleTtc.md +15 -0
  14. data/docs/MontantTotal.md +12 -12
  15. data/docs/MontantTotalAcompte.md +15 -0
  16. data/docs/MontantTotalLigneHt.md +15 -0
  17. data/docs/MontantTvaLigne.md +15 -0
  18. data/docs/MontantTvaTotal.md +15 -0
  19. data/docs/SantApi.md +62 -0
  20. data/docs/SoumettreFactureCompleteResponse.md +1 -1
  21. data/docs/SoumettreFactureRequest.md +3 -3
  22. data/docs/{MontantTva1.md → Tauxmanuel.md} +2 -2
  23. data/lib/factpulse/api/sant_api.rb +57 -0
  24. data/lib/factpulse/api_client.rb +6 -2
  25. data/lib/factpulse/models/{facture_enrichie_info_output.rb → facture_enrichie_info.rb} +3 -3
  26. data/lib/factpulse/models/ligne_de_poste.rb +3 -61
  27. data/lib/factpulse/models/ligne_de_poste_montant_remise_ht.rb +104 -0
  28. data/lib/factpulse/models/ligne_de_poste_taux_tva_manuel.rb +104 -0
  29. data/lib/factpulse/models/ligne_de_tva.rb +3 -49
  30. data/lib/factpulse/models/{montant_tva1.rb → montant_a_payer.rb} +2 -2
  31. data/lib/factpulse/models/montant_base_ht.rb +104 -0
  32. data/lib/factpulse/models/montant_ht_total.rb +1 -0
  33. data/lib/factpulse/models/montant_remise_globale_ttc.rb +104 -0
  34. data/lib/factpulse/models/montant_total.rb +6 -94
  35. data/lib/factpulse/models/{montant_ht_total1.rb → montant_total_acompte.rb} +2 -2
  36. data/lib/factpulse/models/montant_total_ligne_ht.rb +104 -0
  37. data/lib/factpulse/models/montant_ttc_total.rb +1 -0
  38. data/lib/factpulse/models/montant_tva.rb +1 -0
  39. data/lib/factpulse/models/montant_tva_ligne.rb +104 -0
  40. data/lib/factpulse/models/{montant_ttc_total1.rb → montant_tva_total.rb} +2 -2
  41. data/lib/factpulse/models/soumettre_facture_complete_response.rb +1 -1
  42. data/lib/factpulse/models/soumettre_facture_request.rb +3 -3
  43. data/lib/factpulse/models/tauxmanuel.rb +104 -0
  44. data/lib/factpulse/version.rb +1 -1
  45. data/lib/factpulse.rb +11 -5
  46. metadata +24 -12
  47. data/docs/FactureEnrichieInfoInput.md +0 -32
  48. data/lib/factpulse/models/facture_enrichie_info_input.rb +0 -315
@@ -1,4 +1,4 @@
1
- # FactPulse::MontantTva1
1
+ # FactPulse::Tauxmanuel
2
2
 
3
3
  ## Properties
4
4
 
@@ -10,6 +10,6 @@
10
10
  ```ruby
11
11
  require 'factpulse'
12
12
 
13
- instance = FactPulse::MontantTva1.new()
13
+ instance = FactPulse::Tauxmanuel.new()
14
14
  ```
15
15
 
@@ -19,6 +19,63 @@ module FactPulse
19
19
  def initialize(api_client = ApiClient.default)
20
20
  @api_client = api_client
21
21
  end
22
+ # Endpoint de healthcheck pour Docker
23
+ # Endpoint de healthcheck pour Docker et les load balancers. Utile pour : - Docker healthcheck - Kubernetes liveness/readiness probes - Load balancers (Nginx, HAProxy) - Monitoring de disponibilité - Déploiement zero downtime Retourne un code 200 si l'API est opérationnelle.
24
+ # @param [Hash] opts the optional parameters
25
+ # @return [Object]
26
+ def healthcheck_healthcheck_get(opts = {})
27
+ data, _status_code, _headers = healthcheck_healthcheck_get_with_http_info(opts)
28
+ data
29
+ end
30
+
31
+ # Endpoint de healthcheck pour Docker
32
+ # Endpoint de healthcheck pour Docker et les load balancers. Utile pour : - Docker healthcheck - Kubernetes liveness/readiness probes - Load balancers (Nginx, HAProxy) - Monitoring de disponibilité - Déploiement zero downtime Retourne un code 200 si l'API est opérationnelle.
33
+ # @param [Hash] opts the optional parameters
34
+ # @return [Array<(Object, Integer, Hash)>] Object data, response status code and response headers
35
+ def healthcheck_healthcheck_get_with_http_info(opts = {})
36
+ if @api_client.config.debugging
37
+ @api_client.config.logger.debug 'Calling API: SantApi.healthcheck_healthcheck_get ...'
38
+ end
39
+ # resource path
40
+ local_var_path = '/healthcheck'
41
+
42
+ # query parameters
43
+ query_params = opts[:query_params] || {}
44
+
45
+ # header parameters
46
+ header_params = opts[:header_params] || {}
47
+ # HTTP header 'Accept' (if needed)
48
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
49
+
50
+ # form parameters
51
+ form_params = opts[:form_params] || {}
52
+
53
+ # http body (model)
54
+ post_body = opts[:debug_body]
55
+
56
+ # return_type
57
+ return_type = opts[:debug_return_type] || 'Object'
58
+
59
+ # auth_names
60
+ auth_names = opts[:debug_auth_names] || []
61
+
62
+ new_options = opts.merge(
63
+ :operation => :"SantApi.healthcheck_healthcheck_get",
64
+ :header_params => header_params,
65
+ :query_params => query_params,
66
+ :form_params => form_params,
67
+ :body => post_body,
68
+ :auth_names => auth_names,
69
+ :return_type => return_type
70
+ )
71
+
72
+ data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
73
+ if @api_client.config.debugging
74
+ @api_client.config.logger.debug "API called: SantApi#healthcheck_healthcheck_get\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
75
+ end
76
+ return data, status_code, headers
77
+ end
78
+
22
79
  # Vérifier l'état de l'API
23
80
  # Endpoint de health check pour vérifier que l'API répond. Utile pour : - Monitoring de disponibilité - Tests d'intégration - Load balancers
24
81
  # @param [Hash] opts the optional parameters
@@ -278,9 +278,13 @@ module FactPulse
278
278
  data.each { |k, v| hash[k] = convert_to_type(v, sub_type) }
279
279
  end
280
280
  else
281
- # models (e.g. Pet) or oneOf
281
+ # models (e.g. Pet) or oneOf/anyOf
282
282
  klass = FactPulse.const_get(return_type)
283
- klass.respond_to?(:openapi_one_of) ? klass.build(data) : klass.build_from_hash(data)
283
+ if klass.respond_to?(:openapi_one_of) || klass.respond_to?(:openapi_any_of)
284
+ klass.build(data)
285
+ else
286
+ klass.build_from_hash(data)
287
+ end
284
288
  end
285
289
  end
286
290
 
@@ -15,7 +15,7 @@ require 'time'
15
15
 
16
16
  module FactPulse
17
17
  # Informations sur la facture enrichie.
18
- class FactureEnrichieInfoOutput < ApiModelBase
18
+ class FactureEnrichieInfo < ApiModelBase
19
19
  attr_accessor :numero_facture
20
20
 
21
21
  attr_accessor :id_emetteur
@@ -82,14 +82,14 @@ module FactPulse
82
82
  # @param [Hash] attributes Model attributes in the form of hash
83
83
  def initialize(attributes = {})
84
84
  if (!attributes.is_a?(Hash))
85
- fail ArgumentError, "The input argument (attributes) must be a hash in `FactPulse::FactureEnrichieInfoOutput` initialize method"
85
+ fail ArgumentError, "The input argument (attributes) must be a hash in `FactPulse::FactureEnrichieInfo` initialize method"
86
86
  end
87
87
 
88
88
  # check to see if the attribute exists and convert string to symbol for hash key
89
89
  acceptable_attribute_map = self.class.acceptable_attribute_map
90
90
  attributes = attributes.each_with_object({}) { |(k, v), h|
91
91
  if (!acceptable_attribute_map.key?(k.to_sym))
92
- fail ArgumentError, "`#{k}` is not a valid attribute in `FactPulse::FactureEnrichieInfoOutput`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
92
+ fail ArgumentError, "`#{k}` is not a valid attribute in `FactPulse::FactureEnrichieInfo`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
93
93
  end
94
94
  h[k.to_sym] = v
95
95
  }
@@ -28,15 +28,12 @@ module FactPulse
28
28
 
29
29
  attr_accessor :montant_unitaire_ht
30
30
 
31
- # Montant de la remise HT.
32
31
  attr_accessor :montant_remise_ht
33
32
 
34
- # Montant total HT de la ligne (quantité × prix unitaire - remise).
35
33
  attr_accessor :montant_total_ligne_ht
36
34
 
37
35
  attr_accessor :taux_tva
38
36
 
39
- # Taux de TVA avec valeur manuelle.
40
37
  attr_accessor :taux_tva_manuel
41
38
 
42
39
  attr_accessor :categorie_tva
@@ -111,10 +108,10 @@ module FactPulse
111
108
  :'quantite' => :'Quantite',
112
109
  :'unite' => :'Unite',
113
110
  :'montant_unitaire_ht' => :'MontantUnitaireHt',
114
- :'montant_remise_ht' => :'Float',
115
- :'montant_total_ligne_ht' => :'Float',
111
+ :'montant_remise_ht' => :'LigneDePosteMontantRemiseHt',
112
+ :'montant_total_ligne_ht' => :'MontantTotalLigneHt',
116
113
  :'taux_tva' => :'String',
117
- :'taux_tva_manuel' => :'Float',
114
+ :'taux_tva_manuel' => :'LigneDePosteTauxTvaManuel',
118
115
  :'categorie_tva' => :'CategorieTVA',
119
116
  :'date_debut_periode' => :'String',
120
117
  :'date_fin_periode' => :'String',
@@ -250,21 +247,6 @@ module FactPulse
250
247
  invalid_properties.push('invalid value for "montant_unitaire_ht", montant_unitaire_ht cannot be nil.')
251
248
  end
252
249
 
253
- pattern = Regexp.new(/^(?!^[-+.]*$)[+-]?0*(?:\d{0,8}|(?=[\d.]{1,13}0*$)\d{0,8}\.\d{0,4}0*$)/)
254
- if !@montant_remise_ht.nil? && @montant_remise_ht !~ pattern
255
- invalid_properties.push("invalid value for \"montant_remise_ht\", must conform to the pattern #{pattern}.")
256
- end
257
-
258
- pattern = Regexp.new(/^(?!^[-+.]*$)[+-]?0*(?:\d{0,10}|(?=[\d.]{1,13}0*$)\d{0,10}\.\d{0,2}0*$)/)
259
- if !@montant_total_ligne_ht.nil? && @montant_total_ligne_ht !~ pattern
260
- invalid_properties.push("invalid value for \"montant_total_ligne_ht\", must conform to the pattern #{pattern}.")
261
- end
262
-
263
- pattern = Regexp.new(/^(?!^[-+.]*$)[+-]?0*(?:\d{0,8}|(?=[\d.]{1,13}0*$)\d{0,8}\.\d{0,4}0*$)/)
264
- if !@taux_tva_manuel.nil? && @taux_tva_manuel !~ pattern
265
- invalid_properties.push("invalid value for \"taux_tva_manuel\", must conform to the pattern #{pattern}.")
266
- end
267
-
268
250
  invalid_properties
269
251
  end
270
252
 
@@ -277,9 +259,6 @@ module FactPulse
277
259
  return false if @quantite.nil?
278
260
  return false if @unite.nil?
279
261
  return false if @montant_unitaire_ht.nil?
280
- return false if !@montant_remise_ht.nil? && @montant_remise_ht !~ Regexp.new(/^(?!^[-+.]*$)[+-]?0*(?:\d{0,8}|(?=[\d.]{1,13}0*$)\d{0,8}\.\d{0,4}0*$)/)
281
- return false if !@montant_total_ligne_ht.nil? && @montant_total_ligne_ht !~ Regexp.new(/^(?!^[-+.]*$)[+-]?0*(?:\d{0,10}|(?=[\d.]{1,13}0*$)\d{0,10}\.\d{0,2}0*$)/)
282
- return false if !@taux_tva_manuel.nil? && @taux_tva_manuel !~ Regexp.new(/^(?!^[-+.]*$)[+-]?0*(?:\d{0,8}|(?=[\d.]{1,13}0*$)\d{0,8}\.\d{0,4}0*$)/)
283
262
  true
284
263
  end
285
264
 
@@ -333,43 +312,6 @@ module FactPulse
333
312
  @montant_unitaire_ht = montant_unitaire_ht
334
313
  end
335
314
 
336
- # Custom attribute writer method with validation
337
- # @param [Object] montant_remise_ht Value to be assigned
338
- def montant_remise_ht=(montant_remise_ht)
339
- pattern = Regexp.new(/^(?!^[-+.]*$)[+-]?0*(?:\d{0,8}|(?=[\d.]{1,13}0*$)\d{0,8}\.\d{0,4}0*$)/)
340
- if !montant_remise_ht.nil? && montant_remise_ht !~ pattern
341
- fail ArgumentError, "invalid value for \"montant_remise_ht\", must conform to the pattern #{pattern}."
342
- end
343
-
344
- @montant_remise_ht = montant_remise_ht
345
- end
346
-
347
- # Custom attribute writer method with validation
348
- # @param [Object] montant_total_ligne_ht Value to be assigned
349
- def montant_total_ligne_ht=(montant_total_ligne_ht)
350
- if montant_total_ligne_ht.nil?
351
- fail ArgumentError, 'montant_total_ligne_ht cannot be nil'
352
- end
353
-
354
- pattern = Regexp.new(/^(?!^[-+.]*$)[+-]?0*(?:\d{0,10}|(?=[\d.]{1,13}0*$)\d{0,10}\.\d{0,2}0*$)/)
355
- if montant_total_ligne_ht !~ pattern
356
- fail ArgumentError, "invalid value for \"montant_total_ligne_ht\", must conform to the pattern #{pattern}."
357
- end
358
-
359
- @montant_total_ligne_ht = montant_total_ligne_ht
360
- end
361
-
362
- # Custom attribute writer method with validation
363
- # @param [Object] taux_tva_manuel Value to be assigned
364
- def taux_tva_manuel=(taux_tva_manuel)
365
- pattern = Regexp.new(/^(?!^[-+.]*$)[+-]?0*(?:\d{0,8}|(?=[\d.]{1,13}0*$)\d{0,8}\.\d{0,4}0*$)/)
366
- if !taux_tva_manuel.nil? && taux_tva_manuel !~ pattern
367
- fail ArgumentError, "invalid value for \"taux_tva_manuel\", must conform to the pattern #{pattern}."
368
- end
369
-
370
- @taux_tva_manuel = taux_tva_manuel
371
- end
372
-
373
315
  # Checks equality by comparing each attribute.
374
316
  # @param [Object] Object to be compared
375
317
  def ==(o)
@@ -0,0 +1,104 @@
1
+ =begin
2
+ #API REST FactPulse
3
+
4
+ # API REST pour la facturation électronique en France : Factur-X, AFNOR PDP/PA, signatures électroniques. ## 🎯 Fonctionnalités principales ### 📄 Génération de factures Factur-X - **Formats** : XML seul ou PDF/A-3 avec XML embarqué - **Profils** : MINIMUM, BASIC, EN16931, EXTENDED - **Normes** : EN 16931 (directive UE 2014/55), ISO 19005-3 (PDF/A-3), CII (UN/CEFACT) - **🆕 Format simplifié** : Génération à partir de SIRET + auto-enrichissement (API Chorus Pro + Recherche Entreprises) ### ✅ Validation et conformité - **Validation XML** : Schematron (45 à 210+ règles selon profil) - **Validation PDF** : PDF/A-3, métadonnées XMP Factur-X, signatures électroniques - **VeraPDF** : Validation stricte PDF/A (146+ règles ISO 19005-3) - **Traitement asynchrone** : Support Celery pour validations lourdes (VeraPDF) ### 📡 Intégration AFNOR PDP/PA (XP Z12-013) - **Soumission de flux** : Envoi de factures vers Plateformes de Dématérialisation Partenaires - **Recherche de flux** : Consultation des factures soumises - **Téléchargement** : Récupération des PDF/A-3 avec XML - **Directory Service** : Recherche d'entreprises (SIREN/SIRET) - **Multi-client** : Support de plusieurs configs PDP par utilisateur (stored credentials ou zero-storage) ### ✍️ Signature électronique PDF - **Standards** : PAdES-B-B, PAdES-B-T (horodatage RFC 3161), PAdES-B-LT (archivage long terme) - **Niveaux eIDAS** : SES (auto-signé), AdES (CA commerciale), QES (PSCO) - **Validation** : Vérification intégrité cryptographique et certificats - **Génération de certificats** : Certificats X.509 auto-signés pour tests ### 🔄 Traitement asynchrone - **Celery** : Génération, validation et signature asynchrones - **Polling** : Suivi d'état via `/taches/{id_tache}/statut` - **Pas de timeout** : Idéal pour gros fichiers ou validations lourdes ## 🔒 Authentification Toutes les requêtes nécessitent un **token JWT** dans le header Authorization : ``` Authorization: Bearer YOUR_JWT_TOKEN ``` ### Comment obtenir un token JWT ? #### 🔑 Méthode 1 : API `/api/token/` (Recommandée) **URL :** `https://www.factpulse.fr/api/token/` Cette méthode est **recommandée** pour l'intégration dans vos applications et workflows CI/CD. **Prérequis :** Avoir défini un mot de passe sur votre compte **Pour les utilisateurs inscrits via email/password :** - Vous avez déjà un mot de passe, utilisez-le directement **Pour les utilisateurs inscrits via OAuth (Google/GitHub) :** - Vous devez d'abord définir un mot de passe sur : https://www.factpulse.fr/accounts/password/set/ - Une fois le mot de passe créé, vous pourrez utiliser l'API **Exemple de requête :** ```bash curl -X POST https://www.factpulse.fr/api/token/ \\ -H \"Content-Type: application/json\" \\ -d '{ \"username\": \"votre_email@example.com\", \"password\": \"votre_mot_de_passe\" }' ``` **Paramètre optionnel `client_uid` :** Pour sélectionner les credentials d'un client spécifique (PA/PDP, Chorus Pro, certificats de signature), ajoutez `client_uid` : ```bash curl -X POST https://www.factpulse.fr/api/token/ \\ -H \"Content-Type: application/json\" \\ -d '{ \"username\": \"votre_email@example.com\", \"password\": \"votre_mot_de_passe\", \"client_uid\": \"550e8400-e29b-41d4-a716-446655440000\" }' ``` Le `client_uid` sera inclus dans le JWT et permettra à l'API d'utiliser automatiquement : - Les credentials AFNOR/PDP configurés pour ce client - Les credentials Chorus Pro configurés pour ce client - Les certificats de signature électronique configurés pour ce client **Réponse :** ```json { \"access\": \"eyJ0eXAiOiJKV1QiLCJhbGc...\", // Token d'accès (validité: 30 min) \"refresh\": \"eyJ0eXAiOiJKV1QiLCJhbGc...\" // Token de rafraîchissement (validité: 7 jours) } ``` **Avantages :** - ✅ Automatisation complète (CI/CD, scripts) - ✅ Gestion programmatique des tokens - ✅ Support du refresh token pour renouveler automatiquement l'accès - ✅ Intégration facile dans n'importe quel langage/outil #### 🖥️ Méthode 2 : Génération via Dashboard (Alternative) **URL :** https://www.factpulse.fr/dashboard/ Cette méthode convient pour des tests rapides ou une utilisation occasionnelle via l'interface graphique. **Fonctionnement :** - Connectez-vous au dashboard - Utilisez les boutons \"Generate Test Token\" ou \"Generate Production Token\" - Fonctionne pour **tous** les utilisateurs (OAuth et email/password), sans nécessiter de mot de passe **Types de tokens :** - **Token Test** : Validité 24h, quota 1000 appels/jour (gratuit) - **Token Production** : Validité 7 jours, quota selon votre forfait **Avantages :** - ✅ Rapide pour tester l'API - ✅ Aucun mot de passe requis - ✅ Interface visuelle simple **Inconvénients :** - ❌ Nécessite une action manuelle - ❌ Pas de refresh token - ❌ Moins adapté pour l'automatisation ### 📚 Documentation complète Pour plus d'informations sur l'authentification et l'utilisation de l'API : https://www.factpulse.fr/documentation-api/
5
+
6
+ The version of the OpenAPI document: 1.0.0
7
+
8
+ Generated by: https://openapi-generator.tech
9
+ Generator version: 7.18.0-SNAPSHOT
10
+
11
+ =end
12
+
13
+ require 'date'
14
+ require 'time'
15
+
16
+ module FactPulse
17
+ # Montant de la remise HT. (Accepte number, string ou integer)
18
+ module LigneDePosteMontantRemiseHt
19
+ class << self
20
+ # List of class defined in anyOf (OpenAPI v3)
21
+ def openapi_any_of
22
+ [
23
+ :'Float',
24
+ :'String'
25
+ ]
26
+ end
27
+
28
+ # Builds the object
29
+ # @param [Mixed] Data to be matched against the list of anyOf items
30
+ # @return [Object] Returns the model or the data itself
31
+ def build(data)
32
+ # Go through the list of anyOf items and attempt to identify the appropriate one.
33
+ # Note:
34
+ # - No advanced validation of types in some cases (e.g. "x: { type: string }" will happily match { x: 123 })
35
+ # due to the way the deserialization is made in the base_object template (it just casts without verifying).
36
+ # - TODO: scalar values are de facto behaving as if they were nullable.
37
+ # - TODO: logging when debugging is set.
38
+ openapi_any_of.each do |klass|
39
+ begin
40
+ next if klass == :AnyType # "nullable: true"
41
+ return find_and_cast_into_type(klass, data)
42
+ rescue # rescue all errors so we keep iterating even if the current item lookup raises
43
+ end
44
+ end
45
+
46
+ openapi_any_of.include?(:AnyType) ? data : nil
47
+ end
48
+
49
+ private
50
+
51
+ SchemaMismatchError = Class.new(StandardError)
52
+
53
+ # Note: 'File' is missing here because in the regular case we get the data _after_ a call to JSON.parse.
54
+ def find_and_cast_into_type(klass, data)
55
+ return if data.nil?
56
+
57
+ case klass.to_s
58
+ when 'Boolean'
59
+ return data if data.instance_of?(TrueClass) || data.instance_of?(FalseClass)
60
+ when 'Float'
61
+ return data if data.instance_of?(Float)
62
+ when 'Integer'
63
+ return data if data.instance_of?(Integer)
64
+ when 'Time'
65
+ return Time.parse(data)
66
+ when 'Date'
67
+ return Date.iso8601(data)
68
+ when 'String'
69
+ return data if data.instance_of?(String)
70
+ when 'Object' # "type: object"
71
+ return data if data.instance_of?(Hash)
72
+ when /\AArray<(?<sub_type>.+)>\z/ # "type: array"
73
+ if data.instance_of?(Array)
74
+ sub_type = Regexp.last_match[:sub_type]
75
+ return data.map { |item| find_and_cast_into_type(sub_type, item) }
76
+ end
77
+ when /\AHash<String, (?<sub_type>.+)>\z/ # "type: object" with "additionalProperties: { ... }"
78
+ if data.instance_of?(Hash) && data.keys.all? { |k| k.instance_of?(Symbol) || k.instance_of?(String) }
79
+ sub_type = Regexp.last_match[:sub_type]
80
+ return data.each_with_object({}) { |(k, v), hsh| hsh[k] = find_and_cast_into_type(sub_type, v) }
81
+ end
82
+ else # model
83
+ const = FactPulse.const_get(klass)
84
+ if const
85
+ if const.respond_to?(:openapi_any_of) # nested anyOf model
86
+ model = const.build(data)
87
+ return model if model
88
+ else
89
+ # raise if data contains keys that are not known to the model
90
+ raise if const.respond_to?(:acceptable_attributes) && !(data.keys - const.acceptable_attributes).empty?
91
+ model = const.build_from_hash(data)
92
+ return model if model
93
+ end
94
+ end
95
+ end
96
+
97
+ raise # if no match by now, raise
98
+ rescue
99
+ raise SchemaMismatchError, "#{data} doesn't match the #{klass} type"
100
+ end
101
+ end
102
+ end
103
+
104
+ end
@@ -0,0 +1,104 @@
1
+ =begin
2
+ #API REST FactPulse
3
+
4
+ # API REST pour la facturation électronique en France : Factur-X, AFNOR PDP/PA, signatures électroniques. ## 🎯 Fonctionnalités principales ### 📄 Génération de factures Factur-X - **Formats** : XML seul ou PDF/A-3 avec XML embarqué - **Profils** : MINIMUM, BASIC, EN16931, EXTENDED - **Normes** : EN 16931 (directive UE 2014/55), ISO 19005-3 (PDF/A-3), CII (UN/CEFACT) - **🆕 Format simplifié** : Génération à partir de SIRET + auto-enrichissement (API Chorus Pro + Recherche Entreprises) ### ✅ Validation et conformité - **Validation XML** : Schematron (45 à 210+ règles selon profil) - **Validation PDF** : PDF/A-3, métadonnées XMP Factur-X, signatures électroniques - **VeraPDF** : Validation stricte PDF/A (146+ règles ISO 19005-3) - **Traitement asynchrone** : Support Celery pour validations lourdes (VeraPDF) ### 📡 Intégration AFNOR PDP/PA (XP Z12-013) - **Soumission de flux** : Envoi de factures vers Plateformes de Dématérialisation Partenaires - **Recherche de flux** : Consultation des factures soumises - **Téléchargement** : Récupération des PDF/A-3 avec XML - **Directory Service** : Recherche d'entreprises (SIREN/SIRET) - **Multi-client** : Support de plusieurs configs PDP par utilisateur (stored credentials ou zero-storage) ### ✍️ Signature électronique PDF - **Standards** : PAdES-B-B, PAdES-B-T (horodatage RFC 3161), PAdES-B-LT (archivage long terme) - **Niveaux eIDAS** : SES (auto-signé), AdES (CA commerciale), QES (PSCO) - **Validation** : Vérification intégrité cryptographique et certificats - **Génération de certificats** : Certificats X.509 auto-signés pour tests ### 🔄 Traitement asynchrone - **Celery** : Génération, validation et signature asynchrones - **Polling** : Suivi d'état via `/taches/{id_tache}/statut` - **Pas de timeout** : Idéal pour gros fichiers ou validations lourdes ## 🔒 Authentification Toutes les requêtes nécessitent un **token JWT** dans le header Authorization : ``` Authorization: Bearer YOUR_JWT_TOKEN ``` ### Comment obtenir un token JWT ? #### 🔑 Méthode 1 : API `/api/token/` (Recommandée) **URL :** `https://www.factpulse.fr/api/token/` Cette méthode est **recommandée** pour l'intégration dans vos applications et workflows CI/CD. **Prérequis :** Avoir défini un mot de passe sur votre compte **Pour les utilisateurs inscrits via email/password :** - Vous avez déjà un mot de passe, utilisez-le directement **Pour les utilisateurs inscrits via OAuth (Google/GitHub) :** - Vous devez d'abord définir un mot de passe sur : https://www.factpulse.fr/accounts/password/set/ - Une fois le mot de passe créé, vous pourrez utiliser l'API **Exemple de requête :** ```bash curl -X POST https://www.factpulse.fr/api/token/ \\ -H \"Content-Type: application/json\" \\ -d '{ \"username\": \"votre_email@example.com\", \"password\": \"votre_mot_de_passe\" }' ``` **Paramètre optionnel `client_uid` :** Pour sélectionner les credentials d'un client spécifique (PA/PDP, Chorus Pro, certificats de signature), ajoutez `client_uid` : ```bash curl -X POST https://www.factpulse.fr/api/token/ \\ -H \"Content-Type: application/json\" \\ -d '{ \"username\": \"votre_email@example.com\", \"password\": \"votre_mot_de_passe\", \"client_uid\": \"550e8400-e29b-41d4-a716-446655440000\" }' ``` Le `client_uid` sera inclus dans le JWT et permettra à l'API d'utiliser automatiquement : - Les credentials AFNOR/PDP configurés pour ce client - Les credentials Chorus Pro configurés pour ce client - Les certificats de signature électronique configurés pour ce client **Réponse :** ```json { \"access\": \"eyJ0eXAiOiJKV1QiLCJhbGc...\", // Token d'accès (validité: 30 min) \"refresh\": \"eyJ0eXAiOiJKV1QiLCJhbGc...\" // Token de rafraîchissement (validité: 7 jours) } ``` **Avantages :** - ✅ Automatisation complète (CI/CD, scripts) - ✅ Gestion programmatique des tokens - ✅ Support du refresh token pour renouveler automatiquement l'accès - ✅ Intégration facile dans n'importe quel langage/outil #### 🖥️ Méthode 2 : Génération via Dashboard (Alternative) **URL :** https://www.factpulse.fr/dashboard/ Cette méthode convient pour des tests rapides ou une utilisation occasionnelle via l'interface graphique. **Fonctionnement :** - Connectez-vous au dashboard - Utilisez les boutons \"Generate Test Token\" ou \"Generate Production Token\" - Fonctionne pour **tous** les utilisateurs (OAuth et email/password), sans nécessiter de mot de passe **Types de tokens :** - **Token Test** : Validité 24h, quota 1000 appels/jour (gratuit) - **Token Production** : Validité 7 jours, quota selon votre forfait **Avantages :** - ✅ Rapide pour tester l'API - ✅ Aucun mot de passe requis - ✅ Interface visuelle simple **Inconvénients :** - ❌ Nécessite une action manuelle - ❌ Pas de refresh token - ❌ Moins adapté pour l'automatisation ### 📚 Documentation complète Pour plus d'informations sur l'authentification et l'utilisation de l'API : https://www.factpulse.fr/documentation-api/
5
+
6
+ The version of the OpenAPI document: 1.0.0
7
+
8
+ Generated by: https://openapi-generator.tech
9
+ Generator version: 7.18.0-SNAPSHOT
10
+
11
+ =end
12
+
13
+ require 'date'
14
+ require 'time'
15
+
16
+ module FactPulse
17
+ # Taux de TVA avec valeur manuelle. (Accepte number, string ou integer)
18
+ module LigneDePosteTauxTvaManuel
19
+ class << self
20
+ # List of class defined in anyOf (OpenAPI v3)
21
+ def openapi_any_of
22
+ [
23
+ :'Float',
24
+ :'String'
25
+ ]
26
+ end
27
+
28
+ # Builds the object
29
+ # @param [Mixed] Data to be matched against the list of anyOf items
30
+ # @return [Object] Returns the model or the data itself
31
+ def build(data)
32
+ # Go through the list of anyOf items and attempt to identify the appropriate one.
33
+ # Note:
34
+ # - No advanced validation of types in some cases (e.g. "x: { type: string }" will happily match { x: 123 })
35
+ # due to the way the deserialization is made in the base_object template (it just casts without verifying).
36
+ # - TODO: scalar values are de facto behaving as if they were nullable.
37
+ # - TODO: logging when debugging is set.
38
+ openapi_any_of.each do |klass|
39
+ begin
40
+ next if klass == :AnyType # "nullable: true"
41
+ return find_and_cast_into_type(klass, data)
42
+ rescue # rescue all errors so we keep iterating even if the current item lookup raises
43
+ end
44
+ end
45
+
46
+ openapi_any_of.include?(:AnyType) ? data : nil
47
+ end
48
+
49
+ private
50
+
51
+ SchemaMismatchError = Class.new(StandardError)
52
+
53
+ # Note: 'File' is missing here because in the regular case we get the data _after_ a call to JSON.parse.
54
+ def find_and_cast_into_type(klass, data)
55
+ return if data.nil?
56
+
57
+ case klass.to_s
58
+ when 'Boolean'
59
+ return data if data.instance_of?(TrueClass) || data.instance_of?(FalseClass)
60
+ when 'Float'
61
+ return data if data.instance_of?(Float)
62
+ when 'Integer'
63
+ return data if data.instance_of?(Integer)
64
+ when 'Time'
65
+ return Time.parse(data)
66
+ when 'Date'
67
+ return Date.iso8601(data)
68
+ when 'String'
69
+ return data if data.instance_of?(String)
70
+ when 'Object' # "type: object"
71
+ return data if data.instance_of?(Hash)
72
+ when /\AArray<(?<sub_type>.+)>\z/ # "type: array"
73
+ if data.instance_of?(Array)
74
+ sub_type = Regexp.last_match[:sub_type]
75
+ return data.map { |item| find_and_cast_into_type(sub_type, item) }
76
+ end
77
+ when /\AHash<String, (?<sub_type>.+)>\z/ # "type: object" with "additionalProperties: { ... }"
78
+ if data.instance_of?(Hash) && data.keys.all? { |k| k.instance_of?(Symbol) || k.instance_of?(String) }
79
+ sub_type = Regexp.last_match[:sub_type]
80
+ return data.each_with_object({}) { |(k, v), hsh| hsh[k] = find_and_cast_into_type(sub_type, v) }
81
+ end
82
+ else # model
83
+ const = FactPulse.const_get(klass)
84
+ if const
85
+ if const.respond_to?(:openapi_any_of) # nested anyOf model
86
+ model = const.build(data)
87
+ return model if model
88
+ else
89
+ # raise if data contains keys that are not known to the model
90
+ raise if const.respond_to?(:acceptable_attributes) && !(data.keys - const.acceptable_attributes).empty?
91
+ model = const.build_from_hash(data)
92
+ return model if model
93
+ end
94
+ end
95
+ end
96
+
97
+ raise # if no match by now, raise
98
+ rescue
99
+ raise SchemaMismatchError, "#{data} doesn't match the #{klass} type"
100
+ end
101
+ end
102
+ end
103
+
104
+ end
@@ -16,15 +16,12 @@ require 'time'
16
16
  module FactPulse
17
17
  # Représente une ligne de totalisation par taux de TVA.
18
18
  class LigneDeTVA < ApiModelBase
19
- # Montant de la base HT pour cette ligne de TVA.
20
19
  attr_accessor :montant_base_ht
21
20
 
22
- # Montant de la TVA pour cette ligne.
23
21
  attr_accessor :montant_tva
24
22
 
25
23
  attr_accessor :taux
26
24
 
27
- # Taux de TVA avec valeur manuelle.
28
25
  attr_accessor :taux_manuel
29
26
 
30
27
  attr_accessor :categorie
@@ -75,10 +72,10 @@ module FactPulse
75
72
  # Attribute type mapping.
76
73
  def self.openapi_types
77
74
  {
78
- :'montant_base_ht' => :'Float',
79
- :'montant_tva' => :'Float',
75
+ :'montant_base_ht' => :'MontantBaseHt',
76
+ :'montant_tva' => :'MontantTvaLigne',
80
77
  :'taux' => :'String',
81
- :'taux_manuel' => :'Float',
78
+ :'taux_manuel' => :'Tauxmanuel',
82
79
  :'categorie' => :'CategorieTVA'
83
80
  }
84
81
  end
@@ -141,25 +138,10 @@ module FactPulse
141
138
  invalid_properties.push('invalid value for "montant_base_ht", montant_base_ht cannot be nil.')
142
139
  end
143
140
 
144
- pattern = Regexp.new(/^(?!^[-+.]*$)[+-]?0*(?:\d{0,8}|(?=[\d.]{1,13}0*$)\d{0,8}\.\d{0,4}0*$)/)
145
- if @montant_base_ht !~ pattern
146
- invalid_properties.push("invalid value for \"montant_base_ht\", must conform to the pattern #{pattern}.")
147
- end
148
-
149
141
  if @montant_tva.nil?
150
142
  invalid_properties.push('invalid value for "montant_tva", montant_tva cannot be nil.')
151
143
  end
152
144
 
153
- pattern = Regexp.new(/^(?!^[-+.]*$)[+-]?0*(?:\d{0,8}|(?=[\d.]{1,13}0*$)\d{0,8}\.\d{0,4}0*$)/)
154
- if @montant_tva !~ pattern
155
- invalid_properties.push("invalid value for \"montant_tva\", must conform to the pattern #{pattern}.")
156
- end
157
-
158
- pattern = Regexp.new(/^(?!^[-+.]*$)[+-]?0*(?:\d{0,8}|(?=[\d.]{1,13}0*$)\d{0,8}\.\d{0,4}0*$)/)
159
- if !@taux_manuel.nil? && @taux_manuel !~ pattern
160
- invalid_properties.push("invalid value for \"taux_manuel\", must conform to the pattern #{pattern}.")
161
- end
162
-
163
145
  invalid_properties
164
146
  end
165
147
 
@@ -168,10 +150,7 @@ module FactPulse
168
150
  def valid?
169
151
  warn '[DEPRECATED] the `valid?` method is obsolete'
170
152
  return false if @montant_base_ht.nil?
171
- return false if @montant_base_ht !~ Regexp.new(/^(?!^[-+.]*$)[+-]?0*(?:\d{0,8}|(?=[\d.]{1,13}0*$)\d{0,8}\.\d{0,4}0*$)/)
172
153
  return false if @montant_tva.nil?
173
- return false if @montant_tva !~ Regexp.new(/^(?!^[-+.]*$)[+-]?0*(?:\d{0,8}|(?=[\d.]{1,13}0*$)\d{0,8}\.\d{0,4}0*$)/)
174
- return false if !@taux_manuel.nil? && @taux_manuel !~ Regexp.new(/^(?!^[-+.]*$)[+-]?0*(?:\d{0,8}|(?=[\d.]{1,13}0*$)\d{0,8}\.\d{0,4}0*$)/)
175
154
  true
176
155
  end
177
156
 
@@ -182,11 +161,6 @@ module FactPulse
182
161
  fail ArgumentError, 'montant_base_ht cannot be nil'
183
162
  end
184
163
 
185
- pattern = Regexp.new(/^(?!^[-+.]*$)[+-]?0*(?:\d{0,8}|(?=[\d.]{1,13}0*$)\d{0,8}\.\d{0,4}0*$)/)
186
- if montant_base_ht !~ pattern
187
- fail ArgumentError, "invalid value for \"montant_base_ht\", must conform to the pattern #{pattern}."
188
- end
189
-
190
164
  @montant_base_ht = montant_base_ht
191
165
  end
192
166
 
@@ -197,29 +171,9 @@ module FactPulse
197
171
  fail ArgumentError, 'montant_tva cannot be nil'
198
172
  end
199
173
 
200
- pattern = Regexp.new(/^(?!^[-+.]*$)[+-]?0*(?:\d{0,8}|(?=[\d.]{1,13}0*$)\d{0,8}\.\d{0,4}0*$)/)
201
- if montant_tva !~ pattern
202
- fail ArgumentError, "invalid value for \"montant_tva\", must conform to the pattern #{pattern}."
203
- end
204
-
205
174
  @montant_tva = montant_tva
206
175
  end
207
176
 
208
- # Custom attribute writer method with validation
209
- # @param [Object] taux_manuel Value to be assigned
210
- def taux_manuel=(taux_manuel)
211
- if taux_manuel.nil?
212
- fail ArgumentError, 'taux_manuel cannot be nil'
213
- end
214
-
215
- pattern = Regexp.new(/^(?!^[-+.]*$)[+-]?0*(?:\d{0,8}|(?=[\d.]{1,13}0*$)\d{0,8}\.\d{0,4}0*$)/)
216
- if taux_manuel !~ pattern
217
- fail ArgumentError, "invalid value for \"taux_manuel\", must conform to the pattern #{pattern}."
218
- end
219
-
220
- @taux_manuel = taux_manuel
221
- end
222
-
223
177
  # Checks equality by comparing each attribute.
224
178
  # @param [Object] Object to be compared
225
179
  def ==(o)
@@ -14,8 +14,8 @@ require 'date'
14
14
  require 'time'
15
15
 
16
16
  module FactPulse
17
- # Montant TVA
18
- module MontantTva1
17
+ # Montant à payer. (Accepte number, string ou integer)
18
+ module MontantAPayer
19
19
  class << self
20
20
  # List of class defined in anyOf (OpenAPI v3)
21
21
  def openapi_any_of