diff --git a/api.py b/api.py index ffdfc28..8077a9a 100644 --- a/api.py +++ b/api.py @@ -1,6 +1,6 @@ from fastapi import FastAPI, HTTPException, Path, Query, Depends, status, Body from fastapi.middleware.cors import CORSMiddleware -from fastapi.responses import StreamingResponse +from fastapi.responses import StreamingResponse, HTMLResponse, Response from fastapi.encoders import jsonable_encoder from pydantic import BaseModel, Field, EmailStr from typing import List, Optional @@ -71,6 +71,7 @@ from schemas import ( ContactCreate, ContactUpdate, ) +from schemas.documents.reglements import ReglementFactureCreate, ReglementMultipleCreate from schemas.tiers.commercial import ( CollaborateurCreate, CollaborateurDetails, @@ -2874,6 +2875,371 @@ async def obtenir_informations_societe(): raise HTTPException(500, str(e)) +@app.get("/societe/logo", tags=["Société"]) +async def obtenir_logo_societe(): + """Retourne le logo en tant qu'image directe""" + try: + societe = sage_client.lire_informations_societe() + + if not societe or not societe.get("logo_base64"): + raise HTTPException(404, "Logo introuvable") + + import base64 + + image_data = base64.b64decode(societe["logo_base64"]) + + return Response(content=image_data, media_type=societe["logo_content_type"]) + + except HTTPException: + raise + except Exception as e: + logger.error(f"Erreur récupération logo: {e}") + raise HTTPException(500, str(e)) + + +@app.get("/societe/preview", response_class=HTMLResponse, tags=["Société"]) +async def preview_societe(): + """Page HTML pour visualiser les infos société avec logo""" + try: + societe = sage_client.lire_informations_societe() + + if not societe: + return "
Aucun logo disponible
" + + html = f""" + + + + +{str(e)}
" + + +@app.post("/factures/{numero_facture}/valider", status_code=200, tags=["Factures"]) +async def valider_facture( + numero_facture: str, + _: AsyncSession = Depends(get_session), +): + try: + resultat = sage_client.valider_facture(numero_facture) + logger.info( + f"Facture {numero_facture} validée: {resultat.get('action_effectuee')}" + ) + return { + "success": True, + "message": resultat.get("message", "Facture validée"), + "data": resultat, + } + except HTTPException: + raise + except Exception as e: + logger.error(f"Erreur validation facture {numero_facture}: {e}") + raise HTTPException(status_code=500, detail=str(e)) + + +@app.post("/factures/{numero_facture}/devalider", status_code=200, tags=["Factures"]) +async def devalider_facture( + numero_facture: str, + _: AsyncSession = Depends(get_session), +): + try: + resultat = sage_client.devalider_facture(numero_facture) + logger.info( + f"Facture {numero_facture} dévalidée: {resultat.get('action_effectuee')}" + ) + return { + "success": True, + "message": resultat.get("message", "Facture dévalidée"), + "data": resultat, + } + except HTTPException: + raise + except Exception as e: + logger.error(f"Erreur dévalidation facture {numero_facture}: {e}") + raise HTTPException(status_code=500, detail=str(e)) + + +@app.get("/factures/{numero_facture}/statut-validation", tags=["Factures"]) +async def get_statut_validation_facture( + numero_facture: str, + _: AsyncSession = Depends(get_session), +): + try: + resultat = sage_client.get_statut_validation(numero_facture) + return { + "success": True, + "data": resultat, + } + except HTTPException: + raise + except Exception as e: + logger.error(f"Erreur lecture statut {numero_facture}: {e}") + raise HTTPException(status_code=500, detail=str(e)) + + +@app.post("/factures/{numero_facture}/regler", status_code=200, tags=["Règlements"]) +async def regler_facture( + numero_facture: str, + reglement: ReglementFactureCreate, + session: AsyncSession = Depends(get_session), +): + try: + resultat = sage_client.regler_facture( + numero_facture=numero_facture, + montant=float(reglement.montant), + mode_reglement=reglement.mode_reglement, + code_journal=reglement.code_journal, + date_reglement=reglement.date_reglement.isoformat() + if reglement.date_reglement + else None, + reference=reglement.reference or "", + libelle=reglement.libelle or "", + devise_code=reglement.devise_code, + cours_devise=float(reglement.cours_devise) + if reglement.cours_devise + else 1.0, + tva_encaissement=reglement.tva_encaissement, + compte_general=reglement.compte_general, + ) + + logger.info( + f"Règlement facture {numero_facture}: {reglement.montant}€ - " + f"Journal: {reglement.code_journal} - Mode: {reglement.mode_reglement}" + ) + + return { + "success": True, + "message": "Règlement effectué avec succès", + "data": resultat, + } + + except HTTPException: + raise + except Exception as e: + logger.error(f"Erreur règlement facture {numero_facture}: {e}") + raise HTTPException(500, str(e)) + + +@app.post("/reglements/multiple", status_code=200, tags=["Règlements"]) +async def regler_factures_multiple( + reglement: ReglementMultipleCreate, + session: AsyncSession = Depends(get_session), +): + try: + resultat = sage_client.regler_factures_client( + client_code=reglement.client_id, + montant_total=reglement.montant_total, + mode_reglement=reglement.mode_reglement, + date_reglement=reglement.date_reglement.isoformat() + if reglement.date_reglement + else None, + reference=reglement.reference or "", + libelle=reglement.libelle or "", + code_journal=reglement.code_journal, + numeros_factures=reglement.numeros_factures, + ) + + logger.info( + f"Règlement multiple client {reglement.client_id}: " + f"{resultat.get('montant_effectif', 0)}€ sur {resultat.get('nb_factures_reglees', 0)} facture(s)" + ) + + return { + "success": True, + "message": "Règlements effectués avec succès", + "data": resultat, + } + + except HTTPException: + raise + except Exception as e: + logger.error(f"Erreur règlement multiple {reglement.client_id}: {e}") + raise HTTPException(500, str(e)) + + +@app.get("/factures/{numero_facture}/reglements", tags=["Règlements"]) +async def get_reglements_facture( + numero_facture: str, + session: AsyncSession = Depends(get_session), +): + try: + resultat = sage_client.get_reglements_facture(numero_facture) + + return { + "success": True, + "data": resultat, + } + + except HTTPException: + raise + except Exception as e: + logger.error(f"Erreur lecture règlements {numero_facture}: {e}") + raise HTTPException(500, str(e)) + + +@app.get("/clients/{client_id}/reglements", tags=["Règlements"]) +async def get_reglements_client( + client_id: str, + date_debut: Optional[datetime] = Query(None, description="Date début"), + date_fin: Optional[datetime] = Query(None, description="Date fin"), + inclure_soldees: bool = Query(True, description="Inclure les factures soldées"), + session: AsyncSession = Depends(get_session), +): + try: + resultat = sage_client.get_reglements_client( + client_code=client_id, + date_debut=date_debut.isoformat() if date_debut else None, + date_fin=date_fin.isoformat() if date_fin else None, + inclure_soldees=inclure_soldees, + ) + + return { + "success": True, + "data": resultat, + } + + except HTTPException: + raise + except Exception as e: + logger.error(f"Erreur lecture règlements client {client_id}: {e}") + raise HTTPException(500, str(e)) + + +@app.get("/journaux/banque", tags=["Règlements"]) +async def get_journaux_banque(): + try: + resultat = sage_client.get_journaux_banque() + return {"success": True, "data": resultat} + except Exception as e: + logger.error(f"Erreur lecture journaux: {e}") + raise HTTPException(500, str(e)) + + +@app.get("/reglements/modes", tags=["Référentiels"]) +async def get_modes_reglement(): + """Liste des modes de règlement disponibles dans Sage""" + try: + modes = sage_client.get_modes_reglement() + return {"success": True, "data": {"modes": modes}} + except Exception as e: + logger.error(f"Erreur lecture modes règlement: {e}") + raise HTTPException(500, str(e)) + + +@app.get("/devises", tags=["Référentiels"]) +async def get_devises(): + """Liste des devises disponibles dans Sage""" + try: + devises = sage_client.get_devises() + return {"success": True, "data": {"devises": devises}} + except Exception as e: + logger.error(f"Erreur lecture devises: {e}") + raise HTTPException(500, str(e)) + + +@app.get("/journaux/tresorerie", tags=["Référentiels"]) +async def get_journaux_tresorerie(): + """Liste des journaux de trésorerie (banque + caisse)""" + try: + journaux = sage_client.get_journaux_tresorerie() + return {"success": True, "data": {"journaux": journaux}} + except Exception as e: + logger.error(f"Erreur lecture journaux: {e}") + raise HTTPException(500, str(e)) + + +@app.get("/comptes-generaux", tags=["Référentiels"]) +async def get_comptes_generaux( + prefixe: Optional[str] = Query(None, description="Filtre par préfixe"), + type_compte: Optional[str] = Query( + None, + description="client | fournisseur | banque | caisse | tva | produit | charge", + ), +): + """Liste des comptes généraux""" + try: + comptes = sage_client.get_comptes_generaux( + prefixe=prefixe, type_compte=type_compte + ) + return {"success": True, "data": {"comptes": comptes, "total": len(comptes)}} + except Exception as e: + logger.error(f"Erreur lecture comptes généraux: {e}") + raise HTTPException(500, str(e)) + + +@app.get("/tva/taux", tags=["Référentiels"]) +async def get_tva_taux(): + """Liste des taux de TVA""" + try: + taux = sage_client.get_tva_taux() + return {"success": True, "data": {"taux": taux}} + except Exception as e: + logger.error(f"Erreur lecture taux TVA: {e}") + raise HTTPException(500, str(e)) + + +@app.get("/parametres/encaissement", tags=["Référentiels"]) +async def get_parametres_encaissement(): + """Paramètres TVA sur encaissement""" + try: + params = sage_client.get_parametres_encaissement() + return {"success": True, "data": params} + except Exception as e: + logger.error(f"Erreur lecture paramètres encaissement: {e}") + raise HTTPException(500, str(e)) + + @app.get("/health", tags=["System"]) async def health_check( sage: SageGatewayClient = Depends(get_sage_client_for_user), diff --git a/database/models/universign.py b/database/models/universign.py index 8b34ba3..fcb0ffa 100644 --- a/database/models/universign.py +++ b/database/models/universign.py @@ -50,7 +50,7 @@ class LocalDocumentStatus(str, Enum): class SageDocumentType(int, Enum): DEVIS = 0 - BON_COMMANDE = 10 + BON_COMMANDE = 10 PREPARATION = 20 BON_LIVRAISON = 30 BON_RETOUR = 40 @@ -61,8 +61,7 @@ class SageDocumentType(int, Enum): class UniversignTransaction(Base): __tablename__ = "universign_transactions" - # === IDENTIFIANTS === - id = Column(String(36), primary_key=True) # UUID local + id = Column(String(36), primary_key=True) transaction_id = Column( String(255), unique=True, @@ -71,7 +70,6 @@ class UniversignTransaction(Base): comment="ID Universign (ex: tr_abc123)", ) - # === LIEN AVEC LE DOCUMENT SAGE === sage_document_id = Column( String(50), nullable=False, @@ -82,7 +80,6 @@ class UniversignTransaction(Base): SQLEnum(SageDocumentType), nullable=False, comment="Type de document Sage" ) - # === STATUTS UNIVERSIGN (SOURCE DE VÉRITÉ) === universign_status = Column( SQLEnum(UniversignTransactionStatus), nullable=False, @@ -94,7 +91,6 @@ class UniversignTransaction(Base): DateTime, nullable=True, comment="Dernière MAJ du statut Universign" ) - # === STATUT LOCAL (DÉDUIT) === local_status = Column( SQLEnum(LocalDocumentStatus), nullable=False, @@ -103,7 +99,6 @@ class UniversignTransaction(Base): comment="Statut métier simplifié pour l'UI", ) - # === URLS ET MÉTADONNÉES UNIVERSIGN === signer_url = Column(Text, nullable=True, comment="URL de signature") document_url = Column(Text, nullable=True, comment="URL du document signé") @@ -125,17 +120,14 @@ class UniversignTransaction(Base): certificate_url = Column(Text, nullable=True, comment="URL du certificat") - # === SIGNATAIRES === signers_data = Column( Text, nullable=True, comment="JSON des signataires (snapshot)" ) - # === INFORMATIONS MÉTIER === requester_email = Column(String(255), nullable=True) requester_name = Column(String(255), nullable=True) document_name = Column(String(500), nullable=True) - # === DATES CLÉS === created_at = Column( DateTime, default=datetime.now, @@ -150,14 +142,12 @@ class UniversignTransaction(Base): expired_at = Column(DateTime, nullable=True) canceled_at = Column(DateTime, nullable=True) - # === SYNCHRONISATION === last_synced_at = Column( DateTime, nullable=True, comment="Dernière sync réussie avec Universign" ) sync_attempts = Column(Integer, default=0, comment="Nombre de tentatives de sync") sync_error = Column(Text, nullable=True) - # === FLAGS === is_test = Column( Boolean, default=False, comment="Transaction en environnement .alpha" ) @@ -166,7 +156,6 @@ class UniversignTransaction(Base): ) webhook_received = Column(Boolean, default=False, comment="Webhook Universign reçu") - # === RELATION === signers = relationship( "UniversignSigner", back_populates="transaction", cascade="all, delete-orphan" ) @@ -174,7 +163,6 @@ class UniversignTransaction(Base): "UniversignSyncLog", back_populates="transaction", cascade="all, delete-orphan" ) - # === INDEXES COMPOSITES === __table_args__ = ( Index("idx_sage_doc", "sage_document_id", "sage_document_type"), Index("idx_sync_status", "needs_sync", "universign_status"), @@ -190,10 +178,6 @@ class UniversignTransaction(Base): class UniversignSigner(Base): - """ - Détail de chaque signataire d'une transaction - """ - __tablename__ = "universign_signers" id = Column(String(36), primary_key=True) @@ -204,33 +188,27 @@ class UniversignSigner(Base): index=True, ) - # === DONNÉES SIGNATAIRE === email = Column(String(255), nullable=False, index=True) name = Column(String(255), nullable=True) phone = Column(String(50), nullable=True) - # === STATUT === status = Column( SQLEnum(UniversignSignerStatus), default=UniversignSignerStatus.WAITING, nullable=False, ) - # === ACTIONS === viewed_at = Column(DateTime, nullable=True) signed_at = Column(DateTime, nullable=True) refused_at = Column(DateTime, nullable=True) refusal_reason = Column(Text, nullable=True) - # === MÉTADONNÉES === ip_address = Column(String(45), nullable=True) user_agent = Column(Text, nullable=True) signature_method = Column(String(50), nullable=True) - # === ORDRE === order_index = Column(Integer, default=0) - # === RELATION === transaction = relationship("UniversignTransaction", back_populates="signers") def __repr__(self): @@ -238,10 +216,6 @@ class UniversignSigner(Base): class UniversignSyncLog(Base): - """ - Journal de toutes les synchronisations (audit trail) - """ - __tablename__ = "universign_sync_logs" id = Column(Integer, primary_key=True, autoincrement=True) @@ -252,22 +226,18 @@ class UniversignSyncLog(Base): index=True, ) - # === SYNC INFO === sync_type = Column(String(50), nullable=False, comment="webhook, polling, manual") sync_timestamp = Column(DateTime, default=datetime.now, nullable=False, index=True) - # === CHANGEMENTS DÉTECTÉS === previous_status = Column(String(50), nullable=True) new_status = Column(String(50), nullable=True) changes_detected = Column(Text, nullable=True, comment="JSON des changements") - # === RÉSULTAT === success = Column(Boolean, default=True) error_message = Column(Text, nullable=True) http_status_code = Column(Integer, nullable=True) response_time_ms = Column(Integer, nullable=True) - # === RELATION === transaction = relationship("UniversignTransaction", back_populates="sync_logs") def __repr__(self): @@ -287,7 +257,6 @@ class UniversignConfig(Base): api_url = Column(String(500), nullable=False) api_key = Column(String(500), nullable=False, comment="À chiffrer") - # === OPTIONS === webhook_url = Column(String(500), nullable=True) webhook_secret = Column(String(255), nullable=True) diff --git a/sage_client.py b/sage_client.py index f938ab5..6e61085 100644 --- a/sage_client.py +++ b/sage_client.py @@ -431,6 +431,159 @@ class SageGatewayClient: """Lit les informations de la société depuis P_DOSSIER""" return self._get("/sage/societe/info").get("data") + def valider_facture(self, numero_facture: str) -> dict: + response = self._post(f"/sage/factures/{numero_facture}/valider", {}) + return response.get("data", {}) + + def devalider_facture(self, numero_facture: str) -> dict: + response = self._post(f"/sage/factures/{numero_facture}/devalider", {}) + return response.get("data", {}) + + def get_statut_validation(self, numero_facture: str) -> dict: + response = self._get(f"/sage/factures/{numero_facture}/statut-validation") + return response.get("data", {}) + + def regler_facture( + self, + numero_facture: str, + montant: float, + mode_reglement: int = 0, + date_reglement: str = None, + reference: str = "", + libelle: str = "", + code_journal: str = None, + devise_code: int = 0, + cours_devise: float = 1.0, + tva_encaissement: bool = False, + compte_general: str = None, + ) -> dict: + """Règle une facture""" + payload = { + "montant": montant, + "mode_reglement": mode_reglement, + "reference": reference, + "libelle": libelle, + "devise_code": devise_code, + "cours_devise": cours_devise, + "tva_encaissement": tva_encaissement, + } + + # Champs optionnels + if date_reglement: + payload["date_reglement"] = date_reglement + if code_journal: + payload["code_journal"] = code_journal + if compte_general: + payload["compte_general"] = compte_general + + return self._post(f"/sage/factures/{numero_facture}/regler", payload).get( + "data", {} + ) + + def regler_factures_client( + self, + client_code: str, + montant_total: float, + mode_reglement: int = 0, + date_reglement: str = None, + reference: str = "", + libelle: str = "", + code_journal: str = None, + numeros_factures: list = None, + devise_code: int = 0, + cours_devise: float = 1.0, + tva_encaissement: bool = False, + ) -> dict: + """Règle plusieurs factures d'un client""" + payload = { + "client_code": client_code, + "montant_total": montant_total, + "mode_reglement": mode_reglement, + "reference": reference, + "libelle": libelle, + "devise_code": devise_code, + "cours_devise": cours_devise, + "tva_encaissement": tva_encaissement, + } + + if date_reglement: + payload["date_reglement"] = date_reglement + if code_journal: + payload["code_journal"] = code_journal + if numeros_factures: + payload["numeros_factures"] = numeros_factures + + return self._post("/sage/reglements/multiple", payload).get("data", {}) + + def get_reglements_facture(self, numero_facture: str) -> dict: + """Récupère les règlements d'une facture""" + return self._get(f"/sage/factures/{numero_facture}/reglements").get("data", {}) + + def get_reglements_client( + self, + client_code: str, + date_debut: str = None, + date_fin: str = None, + inclure_soldees: bool = True, + ) -> dict: + """Récupère les règlements d'un client""" + params = {"inclure_soldees": inclure_soldees} + if date_debut: + params["date_debut"] = date_debut + if date_fin: + params["date_fin"] = date_fin + + return self._get(f"/sage/clients/{client_code}/reglements", params=params).get( + "data", {} + ) + + def get_journaux_banque(self) -> dict: + return self._get("/sage/journaux/banque").get("data", {}) + + def get_modes_reglement(self) -> List[dict]: + """Récupère les modes de règlement depuis Sage""" + return self._get("/sage/reglements/modes").get("data", {}).get("modes", []) + + def get_devises(self) -> List[dict]: + """Récupère les devises disponibles""" + return self._get("/sage/devises").get("data", {}).get("devises", []) + + def get_journaux_tresorerie(self) -> List[dict]: + """Récupère les journaux de trésorerie (banque + caisse)""" + return ( + self._get("/sage/journaux/tresorerie").get("data", {}).get("journaux", []) + ) + + def get_comptes_generaux( + self, prefixe: str = None, type_compte: str = None + ) -> List[dict]: + """ + Récupère les comptes généraux + + Args: + prefixe: Filtre par préfixe (ex: "41", "51") + type_compte: "client", "fournisseur", "banque", "caisse", "tva" + """ + params = {} + if prefixe: + params["prefixe"] = prefixe + if type_compte: + params["type_compte"] = type_compte + + return ( + self._get("/sage/comptes-generaux", params=params) + .get("data", {}) + .get("comptes", []) + ) + + def get_tva_taux(self) -> List[dict]: + """Récupère les taux de TVA""" + return self._get("/sage/tva/taux").get("data", {}).get("taux", []) + + def get_parametres_encaissement(self) -> dict: + """Récupère les paramètres TVA sur encaissement""" + return self._get("/sage/parametres/encaissement").get("data", {}) + def refresh_cache(self) -> Dict: return self._post("/sage/cache/refresh") diff --git a/schemas/documents/factures.py b/schemas/documents/factures.py index 0ab6e21..2ab3382 100644 --- a/schemas/documents/factures.py +++ b/schemas/documents/factures.py @@ -4,6 +4,7 @@ from datetime import datetime from schemas.documents.ligne_document import LigneDocument + class FactureCreate(BaseModel): client_id: str date_facture: Optional[datetime] = None diff --git a/schemas/documents/reglements.py b/schemas/documents/reglements.py new file mode 100644 index 0000000..3a6248e --- /dev/null +++ b/schemas/documents/reglements.py @@ -0,0 +1,116 @@ +from pydantic import BaseModel, Field, field_validator +from typing import List, Optional +import logging +from decimal import Decimal +from datetime import date + +logger = logging.getLogger(__name__) + + +class ReglementFactureCreate(BaseModel): + """Requête de règlement d'une facture côté VPS""" + + # Montant et devise + montant: Decimal = Field(..., gt=0, description="Montant à régler") + devise_code: Optional[int] = Field(0, description="Code devise (0=EUR par défaut)") + cours_devise: Optional[Decimal] = Field(1.0, description="Cours de la devise") + + # Mode et journal + mode_reglement: int = Field( + ..., ge=0, description="Code mode règlement depuis /reglements/modes" + ) + code_journal: str = Field( + ..., min_length=1, description="Code journal depuis /journaux/tresorerie" + ) + + # Dates + date_reglement: Optional[date] = Field( + None, description="Date du règlement (défaut: aujourd'hui)" + ) + date_echeance: Optional[date] = Field(None, description="Date d'échéance") + + # Références + reference: Optional[str] = Field( + "", max_length=17, description="Référence pièce règlement" + ) + libelle: Optional[str] = Field( + "", max_length=35, description="Libellé du règlement" + ) + + # TVA sur encaissement + tva_encaissement: Optional[bool] = Field( + False, description="Appliquer TVA sur encaissement" + ) + compte_general: Optional[str] = Field(None) + + @field_validator("montant") + def validate_montant(cls, v): + if v <= 0: + raise ValueError("Le montant doit être positif") + return round(v, 2) + + class Config: + json_schema_extra = { + "example": { + "montant": 375.12, + "mode_reglement": 2, + "reference": "CHQ-001", + "code_journal": "BEU", + "date_reglement": "2024-01-01", + "libelle": "Règlement multiple", + "tva_encaissement": False, + "devise_code": 0, + "cours_devise": 1.0, + "date_echeance": "2024-01-31", + } + } + + +class ReglementMultipleCreate(BaseModel): + """Requête de règlement multiple côté VPS""" + + client_id: str = Field(..., description="Code client") + montant_total: Decimal = Field(..., gt=0) + + # Même structure que ReglementFactureCreate + devise_code: Optional[int] = Field(0) + cours_devise: Optional[Decimal] = Field(1.0) + mode_reglement: int = Field(...) + code_journal: str = Field(...) + date_reglement: Optional[date] = None + reference: Optional[str] = Field("") + libelle: Optional[str] = Field("") + tva_encaissement: Optional[bool] = Field(False) + + # Factures spécifiques (optionnel) + numeros_factures: Optional[List[str]] = Field( + None, description="Si vide, règle les plus anciennes en premier" + ) + + @field_validator("client_id", mode="before") + def strip_client_id(cls, v): + return v.replace("\xa0", "").strip() if v else v + + @field_validator("montant_total") + def validate_montant(cls, v): + if v <= 0: + raise ValueError("Le montant doit être positif") + return round(v, 2) + + class Config: + json_schema_extra = { + "example": { + "client_id": "CLI000001", + "montant_total": 1000.00, + "mode_reglement": 2, + "numeros_factures": ["FA00081", "FA00082"], + "reference": "CHQ-001", + "code_journal": "BEU", + "date_reglement": "2024-01-01", + "libelle": "Règlement multiple", + "tva_encaissement": False, + "devise_code": 0, + "cours_devise": 1.0, + "date_echeance": "2024-01-31", + } + } diff --git a/schemas/society/societe.py b/schemas/society/societe.py index 01fa308..08309e5 100644 --- a/schemas/society/societe.py +++ b/schemas/society/societe.py @@ -9,14 +9,12 @@ class ExerciceComptable(BaseModel): class SocieteInfo(BaseModel): - # Identification raison_sociale: str numero_dossier: str siret: Optional[str] = None code_ape: Optional[str] = None numero_tva: Optional[str] = None - # Adresse adresse: Optional[str] = None complement_adresse: Optional[str] = None code_postal: Optional[str] = None @@ -24,27 +22,25 @@ class SocieteInfo(BaseModel): code_region: Optional[str] = None pays: Optional[str] = None - # Contacts telephone: Optional[str] = None telecopie: Optional[str] = None email: Optional[str] = None email_societe: Optional[str] = None site_web: Optional[str] = None - # Informations juridiques capital: float = 0.0 forme_juridique: Optional[str] = None - # Exercices comptables exercices: List[ExerciceComptable] = [] - # Configuration devise_compte: int = 0 devise_equivalent: int = 0 longueur_compte_general: int = 0 longueur_compte_analytique: int = 0 regime_fec: int = 0 - # Autres base_modele: Optional[str] = None marqueur: int = 0 + + logo_base64: Optional[str] = None + logo_content_type: Optional[str] = None