factpulse 2.0.10 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -3
- data/Gemfile.lock +1 -1
- data/README.md +119 -73
- data/docs/ChorusProApi.md +1 -1
- data/docs/{FactureEnrichieInfoOutput.md → FactureEnrichieInfo.md} +2 -2
- data/docs/LigneDePoste.md +6 -6
- data/docs/LigneDePosteMontantRemiseHt.md +15 -0
- data/docs/LigneDePosteTauxTvaManuel.md +15 -0
- data/docs/LigneDeTVA.md +6 -6
- data/docs/{MontantHtTotal1.md → MontantAPayer.md} +2 -2
- data/docs/{MontantTtcTotal1.md → MontantBaseHt.md} +2 -2
- data/docs/MontantRemiseGlobaleTtc.md +15 -0
- data/docs/MontantTotal.md +12 -12
- data/docs/MontantTotalAcompte.md +15 -0
- data/docs/MontantTotalLigneHt.md +15 -0
- data/docs/MontantTvaLigne.md +15 -0
- data/docs/MontantTvaTotal.md +15 -0
- data/docs/SantApi.md +62 -0
- data/docs/SoumettreFactureCompleteResponse.md +1 -1
- data/docs/SoumettreFactureRequest.md +3 -3
- data/docs/{MontantTva1.md → Tauxmanuel.md} +2 -2
- data/lib/factpulse/api/sant_api.rb +57 -0
- data/lib/factpulse/models/{facture_enrichie_info_output.rb → facture_enrichie_info.rb} +3 -3
- data/lib/factpulse/models/ligne_de_poste.rb +3 -61
- data/lib/factpulse/models/ligne_de_poste_montant_remise_ht.rb +104 -0
- data/lib/factpulse/models/ligne_de_poste_taux_tva_manuel.rb +104 -0
- data/lib/factpulse/models/ligne_de_tva.rb +3 -49
- data/lib/factpulse/models/{montant_tva1.rb → montant_a_payer.rb} +2 -2
- data/lib/factpulse/models/montant_base_ht.rb +104 -0
- data/lib/factpulse/models/montant_ht_total.rb +1 -0
- data/lib/factpulse/models/montant_remise_globale_ttc.rb +104 -0
- data/lib/factpulse/models/montant_total.rb +6 -94
- data/lib/factpulse/models/{montant_ht_total1.rb → montant_total_acompte.rb} +2 -2
- data/lib/factpulse/models/montant_total_ligne_ht.rb +104 -0
- data/lib/factpulse/models/montant_ttc_total.rb +1 -0
- data/lib/factpulse/models/montant_tva.rb +1 -0
- data/lib/factpulse/models/montant_tva_ligne.rb +104 -0
- data/lib/factpulse/models/{montant_ttc_total1.rb → montant_tva_total.rb} +2 -2
- data/lib/factpulse/models/soumettre_facture_complete_response.rb +1 -1
- data/lib/factpulse/models/soumettre_facture_request.rb +3 -3
- data/lib/factpulse/models/tauxmanuel.rb +104 -0
- data/lib/factpulse/version.rb +1 -1
- data/lib/factpulse.rb +11 -5
- metadata +24 -12
- data/docs/FactureEnrichieInfoInput.md +0 -32
- data/lib/factpulse/models/facture_enrichie_info_input.rb +0 -315
|
@@ -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
|
|
@@ -15,7 +15,7 @@ require 'time'
|
|
|
15
15
|
|
|
16
16
|
module FactPulse
|
|
17
17
|
# Informations sur la facture enrichie.
|
|
18
|
-
class
|
|
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::
|
|
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::
|
|
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' => :'
|
|
115
|
-
:'montant_total_ligne_ht' => :'
|
|
111
|
+
:'montant_remise_ht' => :'LigneDePosteMontantRemiseHt',
|
|
112
|
+
:'montant_total_ligne_ht' => :'MontantTotalLigneHt',
|
|
116
113
|
:'taux_tva' => :'String',
|
|
117
|
-
:'taux_tva_manuel' => :'
|
|
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' => :'
|
|
79
|
-
:'montant_tva' => :'
|
|
75
|
+
:'montant_base_ht' => :'MontantBaseHt',
|
|
76
|
+
:'montant_tva' => :'MontantTvaLigne',
|
|
80
77
|
:'taux' => :'String',
|
|
81
|
-
:'taux_manuel' => :'
|
|
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
|
|
18
|
-
module
|
|
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
|
|
@@ -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 base HT pour cette ligne de TVA. (Accepte number, string ou integer)
|
|
18
|
+
module MontantBaseHt
|
|
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
|