Added create and update for avoir
This commit is contained in:
parent
204b792015
commit
c15ae79c6a
2 changed files with 270 additions and 0 deletions
229
api.py
229
api.py
|
|
@ -405,6 +405,64 @@ class LivraisonUpdateRequest(BaseModel):
|
|||
}
|
||||
}
|
||||
|
||||
class LigneAvoir(BaseModel):
|
||||
"""Ligne d'avoir"""
|
||||
article_code: str
|
||||
quantite: float
|
||||
prix_unitaire_ht: Optional[float] = None
|
||||
remise_pourcentage: Optional[float] = 0.0
|
||||
|
||||
@field_validator("article_code", mode="before")
|
||||
def strip_insecables(cls, v):
|
||||
return v.replace("\xa0", "").strip()
|
||||
|
||||
|
||||
class AvoirCreateRequest(BaseModel):
|
||||
"""Création d'un avoir"""
|
||||
client_id: str
|
||||
date_avoir: Optional[date] = None
|
||||
lignes: List[LigneAvoir]
|
||||
reference: Optional[str] = None
|
||||
|
||||
class Config:
|
||||
json_schema_extra = {
|
||||
"example": {
|
||||
"client_id": "CLI000001",
|
||||
"date_avoir": "2024-01-15",
|
||||
"reference": "AV-EXT-001",
|
||||
"lignes": [
|
||||
{
|
||||
"article_code": "ART001",
|
||||
"quantite": 5.0,
|
||||
"prix_unitaire_ht": 50.0,
|
||||
"remise_pourcentage": 0.0
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class AvoirUpdateRequest(BaseModel):
|
||||
"""Modification d'un avoir existant"""
|
||||
date_avoir: Optional[date] = None
|
||||
lignes: Optional[List[LigneAvoir]] = None
|
||||
statut: Optional[int] = Field(None, ge=0, le=6)
|
||||
reference: Optional[str] = None
|
||||
|
||||
class Config:
|
||||
json_schema_extra = {
|
||||
"example": {
|
||||
"lignes": [
|
||||
{
|
||||
"article_code": "ART001",
|
||||
"quantite": 10.0,
|
||||
"prix_unitaire_ht": 45.0
|
||||
}
|
||||
],
|
||||
"statut": 2
|
||||
}
|
||||
}
|
||||
|
||||
# =====================================================
|
||||
# SERVICES EXTERNES (Universign)
|
||||
# =====================================================
|
||||
|
|
@ -2475,7 +2533,178 @@ async def lire_avoir(numero: str):
|
|||
logger.error(f"Erreur lecture avoir: {e}")
|
||||
raise HTTPException(500, str(e))
|
||||
|
||||
@app.post("/avoirs", status_code=201, tags=["Avoirs"])
|
||||
async def creer_avoir(
|
||||
avoir: AvoirCreateRequest,
|
||||
session: AsyncSession = Depends(get_session)
|
||||
):
|
||||
"""
|
||||
➕ Création d'un avoir (Bon d'avoir)
|
||||
|
||||
**Workflow typique:**
|
||||
1. Retour marchandise → création d'un avoir
|
||||
2. Geste commercial → création directe d'un avoir (cette route)
|
||||
|
||||
**Champs obligatoires:**
|
||||
- `client_id`: Code du client
|
||||
- `lignes`: Liste des lignes (min 1)
|
||||
|
||||
**Champs optionnels:**
|
||||
- `date_avoir`: Date de l'avoir (par défaut: aujourd'hui)
|
||||
- `reference`: Référence externe (ex: numéro de retour)
|
||||
|
||||
**Note:** Les montants des avoirs sont généralement négatifs (crédits)
|
||||
|
||||
Args:
|
||||
avoir: Données de l'avoir à créer
|
||||
|
||||
Returns:
|
||||
Avoir créé avec son numéro et ses totaux
|
||||
"""
|
||||
try:
|
||||
# Vérifier que le client existe
|
||||
client = sage_client.lire_client(avoir.client_id)
|
||||
if not client:
|
||||
raise HTTPException(404, f"Client {avoir.client_id} introuvable")
|
||||
|
||||
# Préparer les données pour la gateway
|
||||
avoir_data = {
|
||||
"client_id": avoir.client_id,
|
||||
"date_avoir": (
|
||||
avoir.date_avoir.isoformat()
|
||||
if avoir.date_avoir
|
||||
else None
|
||||
),
|
||||
"reference": avoir.reference,
|
||||
"lignes": [
|
||||
{
|
||||
"article_code": l.article_code,
|
||||
"quantite": l.quantite,
|
||||
"prix_unitaire_ht": l.prix_unitaire_ht,
|
||||
"remise_pourcentage": l.remise_pourcentage,
|
||||
}
|
||||
for l in avoir.lignes
|
||||
],
|
||||
}
|
||||
|
||||
# Appel à la gateway Windows
|
||||
resultat = sage_client.creer_avoir(avoir_data)
|
||||
|
||||
logger.info(f"✅ Avoir créé: {resultat.get('numero_avoir')}")
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": "Avoir créé avec succès",
|
||||
"data": {
|
||||
"numero_avoir": resultat["numero_avoir"],
|
||||
"client_id": avoir.client_id,
|
||||
"date_avoir": resultat["date_avoir"],
|
||||
"total_ht": resultat["total_ht"],
|
||||
"total_ttc": resultat["total_ttc"],
|
||||
"nb_lignes": resultat["nb_lignes"],
|
||||
"reference": avoir.reference
|
||||
}
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur création avoir: {e}")
|
||||
raise HTTPException(500, str(e))
|
||||
|
||||
|
||||
@app.put("/avoirs/{id}", tags=["Avoirs"])
|
||||
async def modifier_avoir(
|
||||
id: str,
|
||||
avoir_update: AvoirUpdateRequest,
|
||||
session: AsyncSession = Depends(get_session)
|
||||
):
|
||||
"""
|
||||
✏️ Modification d'un avoir existant
|
||||
|
||||
**Champs modifiables:**
|
||||
- `date_avoir`: Nouvelle date
|
||||
- `lignes`: Nouvelles lignes (remplace toutes les lignes existantes)
|
||||
- `statut`: Nouveau statut
|
||||
- `reference`: Référence externe
|
||||
|
||||
**Restrictions:**
|
||||
- Un avoir transformé (statut=5) ne peut plus être modifié
|
||||
- Un avoir annulé (statut=6) ne peut plus être modifié
|
||||
|
||||
**Note importante:**
|
||||
Si `lignes` est fourni, TOUTES les lignes existantes seront remplacées
|
||||
|
||||
Args:
|
||||
id: Numéro de l'avoir à modifier
|
||||
avoir_update: Champs à mettre à jour
|
||||
|
||||
Returns:
|
||||
Avoir modifié avec ses nouvelles valeurs
|
||||
"""
|
||||
try:
|
||||
# Vérifier que l'avoir existe
|
||||
avoir_existant = sage_client.lire_avoir(id)
|
||||
|
||||
if not avoir_existant:
|
||||
raise HTTPException(404, f"Avoir {id} introuvable")
|
||||
|
||||
# Vérifier le statut
|
||||
statut_actuel = avoir_existant.get("statut", 0)
|
||||
|
||||
if statut_actuel == 5:
|
||||
raise HTTPException(
|
||||
400,
|
||||
f"L'avoir {id} a déjà été transformé et ne peut plus être modifié"
|
||||
)
|
||||
|
||||
if statut_actuel == 6:
|
||||
raise HTTPException(
|
||||
400,
|
||||
f"L'avoir {id} est annulé et ne peut plus être modifié"
|
||||
)
|
||||
|
||||
# Construire les données de mise à jour
|
||||
update_data = {}
|
||||
|
||||
if avoir_update.date_avoir:
|
||||
update_data["date_avoir"] = avoir_update.date_avoir.isoformat()
|
||||
|
||||
if avoir_update.lignes is not None:
|
||||
update_data["lignes"] = [
|
||||
{
|
||||
"article_code": l.article_code,
|
||||
"quantite": l.quantite,
|
||||
"prix_unitaire_ht": l.prix_unitaire_ht,
|
||||
"remise_pourcentage": l.remise_pourcentage,
|
||||
}
|
||||
for l in avoir_update.lignes
|
||||
]
|
||||
|
||||
if avoir_update.statut is not None:
|
||||
update_data["statut"] = avoir_update.statut
|
||||
|
||||
if avoir_update.reference is not None:
|
||||
update_data["reference"] = avoir_update.reference
|
||||
|
||||
# Appel à la gateway Windows
|
||||
resultat = sage_client.modifier_avoir(id, update_data)
|
||||
|
||||
logger.info(f"✅ Avoir {id} modifié avec succès")
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": f"Avoir {id} modifié avec succès",
|
||||
"avoir": resultat
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur modification avoir {id}: {e}")
|
||||
raise HTTPException(500, str(e))
|
||||
|
||||
|
||||
# =====================================================
|
||||
# ENDPOINTS - LIVRAISONS
|
||||
# =====================================================
|
||||
|
|
|
|||
|
|
@ -460,6 +460,47 @@ class SageGatewayClient:
|
|||
"numero": numero,
|
||||
"livraison_data": livraison_data
|
||||
}).get("data", {})
|
||||
|
||||
def creer_avoir(self, avoir_data: Dict) -> Dict:
|
||||
"""
|
||||
➕ Création d'un avoir (Bon d'avoir)
|
||||
|
||||
Args:
|
||||
avoir_data: Dictionnaire contenant:
|
||||
- client_id (str): Code du client
|
||||
- date_avoir (str, optional): Date au format ISO
|
||||
- reference (str, optional): Référence externe
|
||||
- lignes (List[Dict]): Liste des lignes avec:
|
||||
- article_code (str)
|
||||
- quantite (float)
|
||||
- prix_unitaire_ht (float, optional)
|
||||
- remise_pourcentage (float, optional)
|
||||
|
||||
Returns:
|
||||
Avoir créé avec son numéro et ses totaux
|
||||
"""
|
||||
return self._post("/sage/avoirs/create", avoir_data).get("data", {})
|
||||
|
||||
|
||||
def modifier_avoir(self, numero: str, avoir_data: Dict) -> Dict:
|
||||
"""
|
||||
✏️ Modification d'un avoir existant
|
||||
|
||||
Args:
|
||||
numero: Numéro de l'avoir à modifier
|
||||
avoir_data: Dictionnaire contenant les champs à modifier:
|
||||
- date_avoir (str, optional): Nouvelle date
|
||||
- lignes (List, optional): Nouvelles lignes
|
||||
- statut (int, optional): Nouveau statut
|
||||
- reference (str, optional): Nouvelle référence
|
||||
|
||||
Returns:
|
||||
Avoir modifié avec totaux recalculés
|
||||
"""
|
||||
return self._post("/sage/avoirs/update", {
|
||||
"numero": numero,
|
||||
"avoir_data": avoir_data
|
||||
}).get("data", {})
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue