feat(api): add date fields to document models

This commit is contained in:
Fanilo-Nantenaina 2025-12-20 16:19:23 +03:00
parent edfa4a0231
commit dbb2a6f16e
2 changed files with 49 additions and 48 deletions

39
api.py
View file

@ -357,6 +357,8 @@ class LigneDevis(BaseModel):
class DevisRequest(BaseModel):
client_id: str
date_devis: Optional[date] = None
date_livraison: Optional[date] = None
date_expedition: Optional[date] = None
reference: Optional[str] = None
lignes: List[LigneDevis]
@ -564,6 +566,8 @@ class DevisUpdateRequest(BaseModel):
"""Modèle pour modification d'un devis existant"""
date_devis: Optional[date] = None
date_livraison: Optional[date] = None
date_expedition: Optional[date] = None
reference: Optional[str] = None
lignes: Optional[List[LigneDevis]] = None
statut: Optional[int] = Field(None, ge=0, le=6)
@ -572,6 +576,8 @@ class DevisUpdateRequest(BaseModel):
json_schema_extra = {
"example": {
"date_devis": "2024-01-15",
"date_livraison": "2024-01-15",
"date_expedition": "2024-01-15",
"reference": "DEV-001",
"lignes": [
{
@ -604,8 +610,10 @@ class CommandeCreateRequest(BaseModel):
client_id: str
date_commande: Optional[date] = None
date_livraison: Optional[date] = None
date_expedition: Optional[date] = None
lignes: List[LigneCommande]
reference: Optional[str] = None # Référence externe
reference: Optional[str] = None
class Config:
json_schema_extra = {
@ -629,6 +637,8 @@ class CommandeUpdateRequest(BaseModel):
"""Modification d'une commande existante"""
date_commande: Optional[date] = None
date_livraison: Optional[date] = None
date_expedition: Optional[date] = None
lignes: Optional[List[LigneCommande]] = None
statut: Optional[int] = Field(None, ge=0, le=6)
reference: Optional[str] = None
@ -637,6 +647,8 @@ class CommandeUpdateRequest(BaseModel):
json_schema_extra = {
"example": {
"date_commande": "2024-01-15",
"date_livraison": "2024-01-15",
"date_expedition": "2024-01-15",
"reference": "CMD-EXT-001",
"lignes": [
{
@ -668,6 +680,8 @@ class LivraisonCreateRequest(BaseModel):
client_id: str
date_livraison: Optional[date] = None
date_livraison_prevue: Optional[date] = None
date_expedition: Optional[date] = None
lignes: List[LigneLivraison]
reference: Optional[str] = None
@ -693,6 +707,8 @@ class LivraisonUpdateRequest(BaseModel):
"""Modification d'une livraison existante"""
date_livraison: Optional[date] = None
date_livraison_prevue: Optional[date] = None
date_expedition: Optional[date] = None
lignes: Optional[List[LigneLivraison]] = None
statut: Optional[int] = Field(None, ge=0, le=6)
reference: Optional[str] = None
@ -700,6 +716,10 @@ class LivraisonUpdateRequest(BaseModel):
class Config:
json_schema_extra = {
"example": {
"date_livraison": "2024-01-15",
"date_livraison_prevue": "2024-01-15",
"date_expedition": "2024-01-15",
"reference": "BL-EXT-001",
"lignes": [
{
"article_code": "ART001",
@ -730,6 +750,8 @@ class AvoirCreateRequest(BaseModel):
client_id: str
date_avoir: Optional[date] = None
date_livraison: Optional[date] = None
date_expedition: Optional[date] = None
lignes: List[LigneAvoir]
reference: Optional[str] = None
@ -755,6 +777,8 @@ class AvoirUpdateRequest(BaseModel):
"""Modification d'un avoir existant"""
date_avoir: Optional[date] = None
date_livraison: Optional[date] = None
date_expedition: Optional[date] = None
lignes: Optional[List[LigneAvoir]] = None
statut: Optional[int] = Field(None, ge=0, le=6)
reference: Optional[str] = None
@ -762,6 +786,10 @@ class AvoirUpdateRequest(BaseModel):
class Config:
json_schema_extra = {
"example": {
"date_avoir": "2024-01-15",
"date_livraison": "2024-01-15",
"date_expedition": "2024-01-15",
"reference": "AV-EXT-001",
"lignes": [
{
"article_code": "ART001",
@ -792,6 +820,8 @@ class FactureCreateRequest(BaseModel):
client_id: str
date_facture: Optional[date] = None
date_livraison: Optional[date] = None
date_expedition: Optional[date] = None
lignes: List[LigneFacture]
reference: Optional[str] = None
@ -817,6 +847,8 @@ class FactureUpdateRequest(BaseModel):
"""Modification d'une facture existante"""
date_facture: Optional[date] = None
date_livraison: Optional[date] = None
date_expedition: Optional[date] = None
lignes: Optional[List[LigneFacture]] = None
statut: Optional[int] = Field(None, ge=0, le=6)
reference: Optional[str] = None
@ -824,6 +856,9 @@ class FactureUpdateRequest(BaseModel):
class Config:
json_schema_extra = {
"example": {
"date_facture": "2024-01-15",
"date_livraison": "2024-01-15",
"date_expedition": "2024-01-15",
"lignes": [
{
"article_code": "ART001",
@ -1907,7 +1942,7 @@ async def modifier_devis(
if devis_update.statut is not None:
update_data["statut"] = devis_update.statut
if devis_update.reference is not None:
update_data["reference"] = devis_update.reference

View file

@ -7,10 +7,6 @@ logger = logging.getLogger(__name__)
class SageGatewayClient:
"""
Client HTTP pour communiquer avec la gateway Sage Windows
"""
def __init__(self):
self.url = settings.sage_gateway_url.rstrip("/")
self.headers = {
@ -264,9 +260,6 @@ class SageGatewayClient:
"""Lecture d'une livraison avec ses lignes"""
return self._post("/sage/livraisons/get", {"code": numero}).get("data")
# =====================================================
# CACHE (ADMIN)
# =====================================================
def refresh_cache(self) -> Dict:
"""Force le rafraîchissement du cache Windows"""
return self._post("/sage/cache/refresh")
@ -275,9 +268,6 @@ class SageGatewayClient:
"""Récupère les infos du cache Windows"""
return self._get("/sage/cache/info").get("data", {})
# =====================================================
# HEALTH
# =====================================================
def health(self) -> dict:
"""Health check de la gateway Windows"""
try:
@ -336,12 +326,11 @@ class SageGatewayClient:
try:
logger.info(f"📄 Demande génération PDF: doc_id={doc_id}, type={type_doc}")
# Appel HTTP vers la gateway Windows
r = requests.post(
f"{self.url}/sage/documents/generate-pdf",
json={"doc_id": doc_id, "type_doc": type_doc},
headers=self.headers,
timeout=60, # Timeout élevé pour génération PDF
timeout=60,
)
r.raise_for_status()
@ -350,7 +339,6 @@ class SageGatewayClient:
response_data = r.json()
# Vérifier que la réponse contient bien le PDF
if not response_data.get("success"):
error_msg = response_data.get("error", "Erreur inconnue")
raise RuntimeError(f"Gateway a retourné une erreur: {error_msg}")
@ -362,7 +350,6 @@ class SageGatewayClient:
f"PDF vide retourné par la gateway pour {doc_id} (type {type_doc})"
)
# Décoder le base64
pdf_bytes = base64.b64decode(pdf_base64)
logger.info(f"✅ PDF décodé: {len(pdf_bytes)} octets")
@ -409,16 +396,13 @@ class SageGatewayClient:
def get_stats_familles(self) -> Dict:
return self._get("/sage/familles/stats").get("data", {})
def creer_entree_stock(self, entree_data: Dict) -> Dict:
return self._post("/sage/stock/entree", entree_data).get("data", {})
def creer_sortie_stock(self, sortie_data: Dict) -> Dict:
return self._post("/sage/stock/sortie", sortie_data).get("data", {})
def lire_mouvement_stock(self, numero: str) -> Optional[Dict]:
try:
response = self._get(f"/sage/stock/mouvement/{numero}")
@ -427,14 +411,11 @@ class SageGatewayClient:
logger.error(f"Erreur lecture mouvement {numero}: {e}")
return None
def lister_modeles_disponibles(self) -> Dict:
"""Liste les modèles Crystal Reports disponibles"""
try:
r = requests.get(
f"{self.url}/sage/modeles/list",
headers=self.headers,
timeout=30
f"{self.url}/sage/modeles/list", headers=self.headers, timeout=30
)
r.raise_for_status()
return r.json().get("data", {})
@ -442,46 +423,31 @@ class SageGatewayClient:
logger.error(f"❌ Erreur listage modèles: {e}")
raise
def generer_pdf_document(
self,
numero: str,
type_doc: int,
modele: str = None,
base64_encode: bool = True
self, numero: str, type_doc: int, modele: str = None, base64_encode: bool = True
) -> Union[bytes, str, Dict]:
"""
Génère un PDF d'un document Sage
Returns:
Dict: Avec pdf_base64 si base64_encode=True
bytes: Contenu PDF brut si base64_encode=False
"""
try:
params = {
"type_doc": type_doc,
"base64_encode": base64_encode
}
params = {"type_doc": type_doc, "base64_encode": base64_encode}
if modele:
params["modele"] = modele
r = requests.get(
f"{self.url}/sage/documents/{numero}/pdf",
params=params,
headers=self.headers,
timeout=60 # PDF peut prendre du temps
timeout=60,
)
r.raise_for_status()
if base64_encode:
return r.json().get("data", {})
else:
return r.content
except requests.exceptions.RequestException as e:
logger.error(f"❌ Erreur génération PDF: {e}")
raise
sage_client = SageGatewayClient()