Added endpoints for collaborators/commercials/representants
This commit is contained in:
parent
96021205a4
commit
f80ad1adee
5 changed files with 587 additions and 48 deletions
68
main.py
68
main.py
|
|
@ -38,6 +38,10 @@ from schemas import (
|
|||
FamilleCreate,
|
||||
PDFGeneration,
|
||||
DevisUpdate,
|
||||
CollaborateurCreateRequest,
|
||||
CollaborateurListRequest,
|
||||
CollaborateurNumeroRequest,
|
||||
CollaborateurUpdateRequest,
|
||||
)
|
||||
|
||||
logging.basicConfig(
|
||||
|
|
@ -1344,6 +1348,70 @@ def tiers_get(req: CodeRequest):
|
|||
raise HTTPException(500, str(e))
|
||||
|
||||
|
||||
@app.post("/sage/collaborateurs/list", dependencies=[Depends(verify_token)])
|
||||
def collaborateurs_list(req: CollaborateurListRequest):
|
||||
"""Liste tous les collaborateurs"""
|
||||
try:
|
||||
collaborateurs = sage.lister_tous_collaborateurs(
|
||||
req.filtre, req.actifs_seulement
|
||||
)
|
||||
return {"success": True, "data": collaborateurs}
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur liste collaborateurs: {e}")
|
||||
raise HTTPException(500, str(e))
|
||||
|
||||
|
||||
@app.post("/sage/collaborateurs/get", dependencies=[Depends(verify_token)])
|
||||
def collaborateur_get(req: CollaborateurNumeroRequest):
|
||||
"""Lecture d'un collaborateur par numéro"""
|
||||
try:
|
||||
collaborateur = sage.lire_collaborateur(req.numero)
|
||||
if not collaborateur:
|
||||
raise HTTPException(404, f"Collaborateur {req.numero} non trouvé")
|
||||
return {"success": True, "data": collaborateur}
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur lecture collaborateur: {e}")
|
||||
raise HTTPException(500, str(e))
|
||||
|
||||
|
||||
@app.post("/sage/collaborateurs/create", dependencies=[Depends(verify_token)])
|
||||
def collaborateur_create(req: CollaborateurCreateRequest):
|
||||
"""Création d'un collaborateur"""
|
||||
try:
|
||||
data = req.model_dump(exclude_none=True)
|
||||
nouveau = sage.creer_collaborateur(data)
|
||||
|
||||
if not nouveau:
|
||||
raise HTTPException(500, "Échec création collaborateur")
|
||||
|
||||
return {"success": True, "data": nouveau}
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur création collaborateur: {e}")
|
||||
raise HTTPException(500, str(e))
|
||||
|
||||
|
||||
@app.post("/sage/collaborateurs/update", dependencies=[Depends(verify_token)])
|
||||
def collaborateur_update(req: CollaborateurUpdateRequest):
|
||||
"""Modification d'un collaborateur"""
|
||||
try:
|
||||
data = req.model_dump(exclude_unset=True, exclude={"numero"})
|
||||
modifie = sage.modifier_collaborateur(req.numero, data)
|
||||
|
||||
if not modifie:
|
||||
raise HTTPException(404, f"Collaborateur {req.numero} non trouvé")
|
||||
|
||||
return {"success": True, "data": modifie}
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur modification collaborateur: {e}")
|
||||
raise HTTPException(500, str(e))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
uvicorn.run(
|
||||
"main:app",
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ from utils import (
|
|||
)
|
||||
|
||||
from schemas.documents.doc_config import TypeDocumentVente
|
||||
from utils.functions.data.create_doc import _creer_document_vente_unifie
|
||||
from utils.functions.data.create_doc import creer_document_vente
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -1219,7 +1219,7 @@ class SageConnector:
|
|||
|
||||
def creer_devis_enrichi(self, devis_data: dict) -> Dict:
|
||||
"""Crée un devis"""
|
||||
return _creer_document_vente_unifie(self, devis_data, TypeDocumentVente.DEVIS)
|
||||
return creer_document_vente(self, devis_data, TypeDocumentVente.DEVIS)
|
||||
|
||||
def _relire_devis(self, numero_devis, devis_data):
|
||||
"""Relit le devis créé et extrait les informations finales."""
|
||||
|
|
@ -4857,7 +4857,7 @@ class SageConnector:
|
|||
|
||||
def creer_commande_enrichi(self, commande_data: dict) -> Dict:
|
||||
"""Crée une commande"""
|
||||
return _creer_document_vente_unifie(commande_data, TypeDocumentVente.COMMANDE)
|
||||
return creer_document_vente(commande_data, TypeDocumentVente.COMMANDE)
|
||||
|
||||
def modifier_commande(self, numero: str, commande_data: Dict) -> Dict:
|
||||
if not self.cial:
|
||||
|
|
@ -5310,7 +5310,7 @@ class SageConnector:
|
|||
|
||||
def creer_livraison_enrichi(self, livraison_data: dict) -> Dict:
|
||||
"""Crée un bon de livraison"""
|
||||
return _creer_document_vente_unifie(livraison_data, TypeDocumentVente.LIVRAISON)
|
||||
return creer_document_vente(livraison_data, TypeDocumentVente.LIVRAISON)
|
||||
|
||||
def modifier_livraison(self, numero: str, livraison_data: Dict) -> Dict:
|
||||
if not self.cial:
|
||||
|
|
@ -5696,7 +5696,7 @@ class SageConnector:
|
|||
|
||||
def creer_avoir_enrichi(self, avoir_data: dict) -> Dict:
|
||||
"""Crée un avoir"""
|
||||
return _creer_document_vente_unifie(avoir_data, TypeDocumentVente.AVOIR)
|
||||
return creer_document_vente(avoir_data, TypeDocumentVente.AVOIR)
|
||||
|
||||
def modifier_avoir(self, numero: str, avoir_data: Dict) -> Dict:
|
||||
if not self.cial:
|
||||
|
|
@ -6162,7 +6162,7 @@ class SageConnector:
|
|||
|
||||
def creer_facture_enrichi(self, facture_data: dict) -> Dict:
|
||||
"""Crée une facture"""
|
||||
return _creer_document_vente_unifie(facture_data, TypeDocumentVente.FACTURE)
|
||||
return creer_document_vente(facture_data, TypeDocumentVente.FACTURE)
|
||||
|
||||
def modifier_facture(self, numero: str, facture_data: Dict) -> Dict:
|
||||
if not self.cial:
|
||||
|
|
@ -9615,3 +9615,422 @@ class SageConnector:
|
|||
except Exception as e:
|
||||
logger.error(f"✗ Erreur SQL tiers {code}: {e}")
|
||||
return None
|
||||
|
||||
def lister_tous_collaborateurs(self, filtre="", actifs_seulement=True):
|
||||
"""Liste tous les collaborateurs"""
|
||||
try:
|
||||
with self._get_sql_connection() as conn:
|
||||
cursor = conn.cursor()
|
||||
|
||||
query = """
|
||||
SELECT
|
||||
CO_No, CO_Nom, CO_Prenom, CO_Fonction,
|
||||
CO_Adresse, CO_Complement, CO_CodePostal, CO_Ville,
|
||||
CO_CodeRegion, CO_Pays, CO_Service,
|
||||
CO_Vendeur, CO_Caissier, CO_Acheteur,
|
||||
CO_Telephone, CO_Telecopie, CO_EMail, CO_TelPortable,
|
||||
CO_Matricule, CO_Facebook, CO_LinkedIn, CO_Skype,
|
||||
CO_Sommeil, CO_ChefVentes, CO_NoChefVentes
|
||||
FROM F_COLLABORATEUR
|
||||
WHERE 1=1
|
||||
"""
|
||||
|
||||
params = []
|
||||
|
||||
if actifs_seulement:
|
||||
query += " AND CO_Sommeil = 0"
|
||||
|
||||
if filtre:
|
||||
query += " AND (CO_Nom LIKE ? OR CO_Prenom LIKE ?)"
|
||||
params.extend([f"%{filtre}%", f"%{filtre}%"])
|
||||
|
||||
query += " ORDER BY CO_Nom, CO_Prenom"
|
||||
|
||||
cursor.execute(query, params)
|
||||
rows = cursor.fetchall()
|
||||
|
||||
# ⚠️⚠️⚠️ VÉRIFIE CETTE LIGNE ⚠️⚠️⚠️
|
||||
collaborateurs = [self._row_to_collaborateur_dict(row) for row in rows]
|
||||
|
||||
logger.info(f"✓ SQL: {len(collaborateurs)} collaborateurs")
|
||||
return collaborateurs
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"✗ Erreur SQL collaborateurs: {e}")
|
||||
raise RuntimeError(f"Erreur lecture collaborateurs: {str(e)}")
|
||||
|
||||
def lire_collaborateur(self, numero):
|
||||
"""Lit un collaborateur par son numéro"""
|
||||
try:
|
||||
with self._get_sql_connection() as conn:
|
||||
cursor = conn.cursor()
|
||||
|
||||
query = """
|
||||
SELECT
|
||||
CO_No, CO_Nom, CO_Prenom, CO_Fonction,
|
||||
CO_Adresse, CO_Complement, CO_CodePostal, CO_Ville,
|
||||
CO_CodeRegion, CO_Pays, CO_Service,
|
||||
CO_Vendeur, CO_Caissier, CO_Acheteur,
|
||||
CO_Telephone, CO_Telecopie, CO_EMail, CO_TelPortable,
|
||||
CO_Matricule, CO_Facebook, CO_LinkedIn, CO_Skype,
|
||||
CO_Sommeil, CO_ChefVentes, CO_NoChefVentes
|
||||
FROM F_COLLABORATEUR
|
||||
WHERE CO_No = ?
|
||||
"""
|
||||
|
||||
cursor.execute(query, (numero,))
|
||||
row = cursor.fetchone()
|
||||
|
||||
if not row:
|
||||
return None
|
||||
|
||||
# ⚠️ UTILISER LA FONCTION DE CLASSE EXISTANTE
|
||||
collaborateur = self._row_to_collaborateur_dict(row)
|
||||
|
||||
logger.info(
|
||||
f"✓ SQL: Collaborateur {numero} avec {len(collaborateur)} champs"
|
||||
)
|
||||
return collaborateur
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"✗ Erreur SQL collaborateur {numero}: {e}")
|
||||
return None
|
||||
|
||||
def creer_collaborateur(self, data: dict) -> dict:
|
||||
"""Crée un nouveau collaborateur via COM Sage"""
|
||||
if not self.cial:
|
||||
raise RuntimeError("Connexion Sage non établie")
|
||||
|
||||
logger.info(
|
||||
f"📝 Début création collaborateur: {data.get('nom')} {data.get('prenom', '')}"
|
||||
)
|
||||
|
||||
try:
|
||||
with self._com_context(), self._lock_com:
|
||||
transaction_active = False
|
||||
|
||||
try:
|
||||
# Démarrage transaction
|
||||
try:
|
||||
self.cial.CptaApplication.BeginTrans()
|
||||
transaction_active = True
|
||||
logger.debug("✓ Transaction Sage démarrée")
|
||||
except Exception as e:
|
||||
logger.warning(f"BeginTrans échoué (non critique): {e}")
|
||||
|
||||
# ===== FACTORY COLLABORATEUR =====
|
||||
factory_collab = self.cial.FactoryCollaborateur
|
||||
persist_collab = factory_collab.Create()
|
||||
|
||||
# Cast vers l'interface IBOCollaborateur3
|
||||
try:
|
||||
collab_obj = win32com.client.CastTo(
|
||||
persist_collab, "IBOCollaborateur3"
|
||||
)
|
||||
except Exception:
|
||||
# Fallback si IBOCollaborateur3 n'existe pas
|
||||
collab_obj = win32com.client.CastTo(
|
||||
persist_collab, "IBOCollaborateur"
|
||||
)
|
||||
|
||||
logger.info("✓ Objet collaborateur créé")
|
||||
|
||||
# ===== MAPPING ET AFFECTATION CHAMPS =====
|
||||
mapping = {
|
||||
"nom": "CO_Nom",
|
||||
"prenom": "CO_Prenom",
|
||||
"fonction": "CO_Fonction",
|
||||
"adresse": "CO_Adresse",
|
||||
"complement": "CO_Complement",
|
||||
"code_postal": "CO_CodePostal",
|
||||
"ville": "CO_Ville",
|
||||
"region": "CO_CodeRegion",
|
||||
"pays": "CO_Pays",
|
||||
"service": "CO_Service",
|
||||
"telephone": "CO_Telephone",
|
||||
"telecopie": "CO_Telecopie",
|
||||
"email": "CO_EMail",
|
||||
"tel_portable": "CO_TelPortable",
|
||||
"matricule": "CO_Matricule",
|
||||
"facebook": "CO_Facebook",
|
||||
"linkedin": "CO_LinkedIn",
|
||||
"skype": "CO_Skype",
|
||||
"chef_ventes_numero": "CO_NoChefVentes",
|
||||
}
|
||||
|
||||
# Champs texte
|
||||
for py_field, sage_field in mapping.items():
|
||||
if py_field in data and data[py_field] is not None:
|
||||
try:
|
||||
setattr(collab_obj, sage_field, str(data[py_field]))
|
||||
logger.debug(f" ✓ {sage_field}: {data[py_field]}")
|
||||
except Exception as e:
|
||||
logger.warning(f" ⚠ {sage_field} non défini: {e}")
|
||||
|
||||
# ===== CHAMPS BOOLÉENS =====
|
||||
bool_mapping = {
|
||||
"est_vendeur": "CO_Vendeur",
|
||||
"est_caissier": "CO_Caissier",
|
||||
"est_acheteur": "CO_Acheteur",
|
||||
"est_chef_ventes": "CO_ChefVentes",
|
||||
}
|
||||
|
||||
for py_field, sage_field in bool_mapping.items():
|
||||
if py_field in data:
|
||||
try:
|
||||
valeur = 1 if data[py_field] else 0
|
||||
setattr(collab_obj, sage_field, valeur)
|
||||
logger.debug(f" ✓ {sage_field}: {valeur}")
|
||||
except Exception as e:
|
||||
logger.warning(f" ⚠ {sage_field} non défini: {e}")
|
||||
|
||||
# ===== CO_SOMMEIL (inversé: est_actif → 0=actif, 1=inactif) =====
|
||||
if "est_actif" in data:
|
||||
try:
|
||||
valeur_sommeil = 0 if data["est_actif"] else 1
|
||||
collab_obj.CO_Sommeil = valeur_sommeil
|
||||
logger.debug(
|
||||
f" ✓ CO_Sommeil: {valeur_sommeil} (actif={data['est_actif']})"
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(f" ⚠ CO_Sommeil non défini: {e}")
|
||||
|
||||
# ===== WRITE =====
|
||||
collab_obj.Write()
|
||||
logger.info("💾 Collaborateur écrit dans Sage")
|
||||
|
||||
# Commit transaction
|
||||
if transaction_active:
|
||||
try:
|
||||
self.cial.CptaApplication.CommitTrans()
|
||||
logger.info("✓ Transaction committée")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# ===== RÉCUPÉRATION DU NUMÉRO =====
|
||||
try:
|
||||
collab_obj.Read()
|
||||
numero = getattr(collab_obj, "CO_No", None)
|
||||
except Exception:
|
||||
numero = None
|
||||
|
||||
if not numero:
|
||||
raise RuntimeError(
|
||||
"Numéro de collaborateur vide après création"
|
||||
)
|
||||
|
||||
logger.info(f"📄 Collaborateur créé: CO_No={numero}")
|
||||
|
||||
# ===== RELECTURE POUR RETOUR COMPLET =====
|
||||
collaborateur_final = self.lire_collaborateur(numero)
|
||||
|
||||
if not collaborateur_final:
|
||||
raise RuntimeError(
|
||||
f"Impossible de relire le collaborateur {numero}"
|
||||
)
|
||||
|
||||
logger.info(
|
||||
f"✅ COLLABORATEUR CRÉÉ: {numero} - "
|
||||
f"{collaborateur_final['nom']} {collaborateur_final.get('prenom', '')}"
|
||||
)
|
||||
|
||||
return collaborateur_final
|
||||
|
||||
except Exception:
|
||||
if transaction_active:
|
||||
try:
|
||||
self.cial.CptaApplication.RollbackTrans()
|
||||
logger.error("❌ Transaction annulée (rollback)")
|
||||
except Exception:
|
||||
pass
|
||||
raise
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ ERREUR CRÉATION COLLABORATEUR: {e}", exc_info=True)
|
||||
raise RuntimeError(f"Échec création collaborateur: {str(e)}")
|
||||
|
||||
def modifier_collaborateur(self, numero: int, data: dict) -> dict:
|
||||
"""Modifie un collaborateur existant via COM Sage"""
|
||||
if not self.cial:
|
||||
raise RuntimeError("Connexion Sage non établie")
|
||||
|
||||
logger.info(f"📝 Début modification collaborateur CO_No={numero}")
|
||||
|
||||
try:
|
||||
with self._com_context(), self._lock_com:
|
||||
transaction_active = False
|
||||
|
||||
try:
|
||||
# Démarrage transaction
|
||||
try:
|
||||
self.cial.CptaApplication.BeginTrans()
|
||||
transaction_active = True
|
||||
logger.debug("✓ Transaction Sage démarrée")
|
||||
except Exception as e:
|
||||
logger.warning(f"BeginTrans échoué (non critique): {e}")
|
||||
|
||||
# ===== LECTURE DU COLLABORATEUR EXISTANT =====
|
||||
factory_collab = self.cial.FactoryCollaborateur
|
||||
persist_collab = factory_collab.ReadNumero(numero)
|
||||
|
||||
if not persist_collab:
|
||||
raise ValueError(f"Collaborateur {numero} introuvable")
|
||||
|
||||
# Cast vers l'interface IBOCollaborateur3
|
||||
try:
|
||||
collab_obj = win32com.client.CastTo(
|
||||
persist_collab, "IBOCollaborateur3"
|
||||
)
|
||||
except Exception:
|
||||
collab_obj = win32com.client.CastTo(
|
||||
persist_collab, "IBOCollaborateur"
|
||||
)
|
||||
|
||||
collab_obj.Read()
|
||||
logger.info(f"✓ Collaborateur {numero} chargé")
|
||||
|
||||
# ===== MAPPING ET MODIFICATION CHAMPS =====
|
||||
mapping = {
|
||||
"nom": "CO_Nom",
|
||||
"prenom": "CO_Prenom",
|
||||
"fonction": "CO_Fonction",
|
||||
"adresse": "CO_Adresse",
|
||||
"complement": "CO_Complement",
|
||||
"code_postal": "CO_CodePostal",
|
||||
"ville": "CO_Ville",
|
||||
"region": "CO_CodeRegion",
|
||||
"pays": "CO_Pays",
|
||||
"service": "CO_Service",
|
||||
"telephone": "CO_Telephone",
|
||||
"telecopie": "CO_Telecopie",
|
||||
"email": "CO_EMail",
|
||||
"tel_portable": "CO_TelPortable",
|
||||
"matricule": "CO_Matricule",
|
||||
"facebook": "CO_Facebook",
|
||||
"linkedin": "CO_LinkedIn",
|
||||
"skype": "CO_Skype",
|
||||
"chef_ventes_numero": "CO_NoChefVentes",
|
||||
}
|
||||
|
||||
champs_modifies = []
|
||||
|
||||
# Champs texte
|
||||
for py_field, sage_field in mapping.items():
|
||||
if py_field in data:
|
||||
try:
|
||||
valeur = (
|
||||
str(data[py_field])
|
||||
if data[py_field] is not None
|
||||
else ""
|
||||
)
|
||||
setattr(collab_obj, sage_field, valeur)
|
||||
champs_modifies.append(sage_field)
|
||||
logger.debug(f" ✓ {sage_field}: {valeur}")
|
||||
except Exception as e:
|
||||
logger.warning(f" ⚠ {sage_field} non modifié: {e}")
|
||||
|
||||
# ===== CHAMPS BOOLÉENS =====
|
||||
bool_mapping = {
|
||||
"est_vendeur": "CO_Vendeur",
|
||||
"est_caissier": "CO_Caissier",
|
||||
"est_acheteur": "CO_Acheteur",
|
||||
"est_chef_ventes": "CO_ChefVentes",
|
||||
}
|
||||
|
||||
for py_field, sage_field in bool_mapping.items():
|
||||
if py_field in data:
|
||||
try:
|
||||
valeur = 1 if data[py_field] else 0
|
||||
setattr(collab_obj, sage_field, valeur)
|
||||
champs_modifies.append(sage_field)
|
||||
logger.debug(f" ✓ {sage_field}: {valeur}")
|
||||
except Exception as e:
|
||||
logger.warning(f" ⚠ {sage_field} non modifié: {e}")
|
||||
|
||||
# ===== CO_SOMMEIL (inversé) =====
|
||||
if "est_actif" in data:
|
||||
try:
|
||||
valeur_sommeil = 0 if data["est_actif"] else 1
|
||||
collab_obj.CO_Sommeil = valeur_sommeil
|
||||
champs_modifies.append("CO_Sommeil")
|
||||
logger.debug(f" ✓ CO_Sommeil: {valeur_sommeil}")
|
||||
except Exception as e:
|
||||
logger.warning(f" ⚠ CO_Sommeil non modifié: {e}")
|
||||
|
||||
if not champs_modifies:
|
||||
logger.info("ℹ Aucun champ à modifier")
|
||||
return self.lire_collaborateur(numero)
|
||||
|
||||
# ===== WRITE =====
|
||||
collab_obj.Write()
|
||||
logger.info(
|
||||
f"💾 Collaborateur modifié ({len(champs_modifies)} champs)"
|
||||
)
|
||||
|
||||
# Commit transaction
|
||||
if transaction_active:
|
||||
try:
|
||||
self.cial.CptaApplication.CommitTrans()
|
||||
logger.info("✓ Transaction committée")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# ===== RELECTURE POUR RETOUR COMPLET =====
|
||||
collaborateur_final = self.lire_collaborateur(numero)
|
||||
|
||||
if not collaborateur_final:
|
||||
raise RuntimeError(
|
||||
f"Impossible de relire le collaborateur {numero}"
|
||||
)
|
||||
|
||||
logger.info(
|
||||
f"✅ COLLABORATEUR MODIFIÉ: {numero} - "
|
||||
f"{collaborateur_final['nom']} {collaborateur_final.get('prenom', '')}"
|
||||
)
|
||||
|
||||
return collaborateur_final
|
||||
|
||||
except Exception:
|
||||
if transaction_active:
|
||||
try:
|
||||
self.cial.CptaApplication.RollbackTrans()
|
||||
logger.error("❌ Transaction annulée (rollback)")
|
||||
except Exception:
|
||||
pass
|
||||
raise
|
||||
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"❌ ERREUR MODIFICATION COLLABORATEUR {numero}: {e}", exc_info=True
|
||||
)
|
||||
raise RuntimeError(f"Échec modification collaborateur: {str(e)}")
|
||||
|
||||
def _row_to_collaborateur_dict(self, row):
|
||||
"""Convertit une ligne SQL en dictionnaire collaborateur"""
|
||||
return {
|
||||
"numero": row.CO_No,
|
||||
"nom": _safe_strip(row.CO_Nom), # ⚠️ Utiliser _safe_strip
|
||||
"prenom": _safe_strip(row.CO_Prenom),
|
||||
"fonction": _safe_strip(row.CO_Fonction),
|
||||
"adresse": _safe_strip(row.CO_Adresse),
|
||||
"complement": _safe_strip(row.CO_Complement),
|
||||
"code_postal": _safe_strip(row.CO_CodePostal),
|
||||
"ville": _safe_strip(row.CO_Ville),
|
||||
"code_region": _safe_strip(row.CO_CodeRegion),
|
||||
"pays": _safe_strip(row.CO_Pays),
|
||||
"service": _safe_strip(row.CO_Service),
|
||||
"vendeur": bool(row.CO_Vendeur),
|
||||
"caissier": bool(row.CO_Caissier),
|
||||
"acheteur": bool(row.CO_Acheteur),
|
||||
"telephone": _safe_strip(row.CO_Telephone),
|
||||
"telecopie": _safe_strip(row.CO_Telecopie),
|
||||
"email": _safe_strip(row.CO_EMail),
|
||||
"tel_portable": _safe_strip(row.CO_TelPortable),
|
||||
"matricule": _safe_strip(row.CO_Matricule),
|
||||
"facebook": _safe_strip(row.CO_Facebook),
|
||||
"linkedin": _safe_strip(row.CO_LinkedIn),
|
||||
"skype": _safe_strip(row.CO_Skype),
|
||||
"sommeil": bool(row.CO_Sommeil),
|
||||
"chef_ventes": bool(row.CO_ChefVentes),
|
||||
"numero_chef_ventes": row.CO_NoChefVentes if row.CO_NoChefVentes else None,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,4 @@
|
|||
from schemas.tiers.tiers import (
|
||||
TiersList,
|
||||
TypeTiers
|
||||
)
|
||||
from schemas.tiers.tiers import TiersList, TypeTiers
|
||||
from schemas.tiers.contact import (
|
||||
ContactCreate,
|
||||
ContactDelete,
|
||||
|
|
@ -9,65 +6,51 @@ from schemas.tiers.contact import (
|
|||
ContactList,
|
||||
ContactUpdate,
|
||||
)
|
||||
from schemas.tiers.clients import (
|
||||
ClientCreate,
|
||||
ClientUpdate
|
||||
)
|
||||
from schemas.tiers.clients import ClientCreate, ClientUpdate
|
||||
|
||||
from schemas.others.general_schema import (
|
||||
FiltreRequest,
|
||||
ChampLibre,
|
||||
CodeRequest,
|
||||
StatutRequest
|
||||
StatutRequest,
|
||||
)
|
||||
|
||||
from schemas.documents.documents import (
|
||||
TransformationRequest,
|
||||
TypeDocument,
|
||||
DocumentGet,
|
||||
PDFGeneration
|
||||
PDFGeneration,
|
||||
)
|
||||
|
||||
from schemas.documents.devis import (
|
||||
DevisRequest,
|
||||
DevisUpdate
|
||||
)
|
||||
from schemas.documents.devis import DevisRequest, DevisUpdate
|
||||
|
||||
from schemas.tiers.fournisseurs import (
|
||||
FournisseurCreate,
|
||||
FournisseurUpdate
|
||||
)
|
||||
from schemas.tiers.fournisseurs import FournisseurCreate, FournisseurUpdate
|
||||
|
||||
from schemas.documents.avoirs import (
|
||||
AvoirCreate,
|
||||
AvoirUpdate
|
||||
)
|
||||
from schemas.documents.avoirs import AvoirCreate, AvoirUpdate
|
||||
|
||||
from schemas.documents.commandes import (
|
||||
CommandeCreate,
|
||||
CommandeUpdate
|
||||
)
|
||||
from schemas.documents.commandes import CommandeCreate, CommandeUpdate
|
||||
|
||||
from schemas.documents.factures import (
|
||||
FactureCreate,
|
||||
FactureUpdate
|
||||
)
|
||||
from schemas.documents.factures import FactureCreate, FactureUpdate
|
||||
|
||||
from schemas.documents.livraisons import (
|
||||
LivraisonCreate,
|
||||
LivraisonUpdate
|
||||
)
|
||||
from schemas.documents.livraisons import LivraisonCreate, LivraisonUpdate
|
||||
|
||||
from schemas.articles.articles import (
|
||||
ArticleCreate,
|
||||
ArticleUpdate,
|
||||
MouvementStockLigneRequest,
|
||||
EntreeStock,
|
||||
SortieStock
|
||||
SortieStock,
|
||||
)
|
||||
|
||||
from schemas.articles.famille_d_articles import FamilleCreate
|
||||
|
||||
from schemas.tiers.commercial import (
|
||||
CollaborateurCreateRequest,
|
||||
CollaborateurListRequest,
|
||||
CollaborateurNumeroRequest,
|
||||
CollaborateurUpdateRequest,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"TiersList",
|
||||
"ContactCreate",
|
||||
|
|
@ -103,5 +86,9 @@ __all__ = [
|
|||
"EntreeStock",
|
||||
"SortieStock",
|
||||
"FamilleCreate",
|
||||
"PDFGeneration"
|
||||
"PDFGeneration",
|
||||
"CollaborateurCreateRequest",
|
||||
"CollaborateurListRequest",
|
||||
"CollaborateurNumeroRequest",
|
||||
"CollaborateurUpdateRequest",
|
||||
]
|
||||
|
|
|
|||
65
schemas/tiers/commercial.py
Normal file
65
schemas/tiers/commercial.py
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
from pydantic import BaseModel
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class CollaborateurListRequest(BaseModel):
|
||||
filtre: str = ""
|
||||
actifs_seulement: bool = True
|
||||
|
||||
|
||||
class CollaborateurNumeroRequest(BaseModel):
|
||||
numero: int
|
||||
|
||||
|
||||
class CollaborateurCreateRequest(BaseModel):
|
||||
nom: str
|
||||
prenom: Optional[str] = None
|
||||
fonction: Optional[str] = None
|
||||
adresse: Optional[str] = None
|
||||
complement: Optional[str] = None
|
||||
code_postal: Optional[str] = None
|
||||
ville: Optional[str] = None
|
||||
code_region: Optional[str] = None
|
||||
pays: Optional[str] = None
|
||||
service: Optional[str] = None
|
||||
vendeur: bool = False
|
||||
caissier: bool = False
|
||||
acheteur: bool = False
|
||||
chef_ventes: bool = False
|
||||
numero_chef_ventes: Optional[int] = None
|
||||
telephone: Optional[str] = None
|
||||
telecopie: Optional[str] = None
|
||||
email: Optional[str] = None
|
||||
tel_portable: Optional[str] = None
|
||||
facebook: Optional[str] = None
|
||||
linkedin: Optional[str] = None
|
||||
skype: Optional[str] = None
|
||||
matricule: Optional[str] = None
|
||||
sommeil: bool = False
|
||||
|
||||
|
||||
class CollaborateurUpdateRequest(CollaborateurNumeroRequest):
|
||||
nom: Optional[str] = None
|
||||
prenom: Optional[str] = None
|
||||
fonction: Optional[str] = None
|
||||
adresse: Optional[str] = None
|
||||
complement: Optional[str] = None
|
||||
code_postal: Optional[str] = None
|
||||
ville: Optional[str] = None
|
||||
code_region: Optional[str] = None
|
||||
pays: Optional[str] = None
|
||||
service: Optional[str] = None
|
||||
vendeur: Optional[bool] = None
|
||||
caissier: Optional[bool] = None
|
||||
acheteur: Optional[bool] = None
|
||||
chef_ventes: Optional[bool] = None
|
||||
numero_chef_ventes: Optional[int] = None
|
||||
telephone: Optional[str] = None
|
||||
telecopie: Optional[str] = None
|
||||
email: Optional[str] = None
|
||||
tel_portable: Optional[str] = None
|
||||
facebook: Optional[str] = None
|
||||
linkedin: Optional[str] = None
|
||||
skype: Optional[str] = None
|
||||
matricule: Optional[str] = None
|
||||
sommeil: Optional[bool] = None
|
||||
|
|
@ -11,7 +11,7 @@ from utils.tiers.clients.clients_data import _cast_client
|
|||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _creer_document_vente_unifie(
|
||||
def creer_document_vente(
|
||||
self, doc_data: dict, type_document: TypeDocumentVente
|
||||
) -> Dict:
|
||||
if not self.cial:
|
||||
|
|
@ -206,7 +206,7 @@ def _appliquer_remise_ligne(ligne_obj, remise_pourcent: float) -> bool:
|
|||
# 3. Calcul (optionnel mais recommandé)
|
||||
try:
|
||||
remise_wrapper.Calcul()
|
||||
except:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 4. Write la ligne
|
||||
|
|
@ -240,7 +240,7 @@ def _ajouter_ligne_document(
|
|||
ligne_persist = factory_lignes.Create()
|
||||
try:
|
||||
ligne_obj = win32com.client.CastTo(ligne_persist, "IBODocumentLigne3")
|
||||
except:
|
||||
except Exception:
|
||||
ligne_obj = win32com.client.CastTo(ligne_persist, "IBODocumentVenteLigne3")
|
||||
|
||||
quantite = float(ligne_data["quantite"])
|
||||
|
|
@ -248,10 +248,10 @@ def _ajouter_ligne_document(
|
|||
# ===== ASSOCIATION ARTICLE =====
|
||||
try:
|
||||
ligne_obj.SetDefaultArticleReference(ligne_data["article_code"], quantite)
|
||||
except:
|
||||
except Exception:
|
||||
try:
|
||||
ligne_obj.SetDefaultArticle(article_obj, quantite)
|
||||
except:
|
||||
except Exception:
|
||||
ligne_obj.DL_Design = designation_sage
|
||||
ligne_obj.DL_Qte = quantite
|
||||
|
||||
|
|
@ -384,7 +384,7 @@ def _relire_document_final(
|
|||
|
||||
|
||||
__all__ = [
|
||||
"_creer_document_vente_unifie",
|
||||
"creer_document_vente",
|
||||
"_ajouter_ligne_document",
|
||||
"_configurer_facture",
|
||||
"_recuperer_numero_document",
|
||||
|
|
|
|||
Loading…
Reference in a new issue