feat(api): add date fields to document models
This commit is contained in:
parent
edfa4a0231
commit
dbb2a6f16e
2 changed files with 49 additions and 48 deletions
37
api.py
37
api.py
|
|
@ -357,6 +357,8 @@ class LigneDevis(BaseModel):
|
||||||
class DevisRequest(BaseModel):
|
class DevisRequest(BaseModel):
|
||||||
client_id: str
|
client_id: str
|
||||||
date_devis: Optional[date] = None
|
date_devis: Optional[date] = None
|
||||||
|
date_livraison: Optional[date] = None
|
||||||
|
date_expedition: Optional[date] = None
|
||||||
reference: Optional[str] = None
|
reference: Optional[str] = None
|
||||||
lignes: List[LigneDevis]
|
lignes: List[LigneDevis]
|
||||||
|
|
||||||
|
|
@ -564,6 +566,8 @@ class DevisUpdateRequest(BaseModel):
|
||||||
"""Modèle pour modification d'un devis existant"""
|
"""Modèle pour modification d'un devis existant"""
|
||||||
|
|
||||||
date_devis: Optional[date] = None
|
date_devis: Optional[date] = None
|
||||||
|
date_livraison: Optional[date] = None
|
||||||
|
date_expedition: Optional[date] = None
|
||||||
reference: Optional[str] = None
|
reference: Optional[str] = None
|
||||||
lignes: Optional[List[LigneDevis]] = None
|
lignes: Optional[List[LigneDevis]] = None
|
||||||
statut: Optional[int] = Field(None, ge=0, le=6)
|
statut: Optional[int] = Field(None, ge=0, le=6)
|
||||||
|
|
@ -572,6 +576,8 @@ class DevisUpdateRequest(BaseModel):
|
||||||
json_schema_extra = {
|
json_schema_extra = {
|
||||||
"example": {
|
"example": {
|
||||||
"date_devis": "2024-01-15",
|
"date_devis": "2024-01-15",
|
||||||
|
"date_livraison": "2024-01-15",
|
||||||
|
"date_expedition": "2024-01-15",
|
||||||
"reference": "DEV-001",
|
"reference": "DEV-001",
|
||||||
"lignes": [
|
"lignes": [
|
||||||
{
|
{
|
||||||
|
|
@ -604,8 +610,10 @@ class CommandeCreateRequest(BaseModel):
|
||||||
|
|
||||||
client_id: str
|
client_id: str
|
||||||
date_commande: Optional[date] = None
|
date_commande: Optional[date] = None
|
||||||
|
date_livraison: Optional[date] = None
|
||||||
|
date_expedition: Optional[date] = None
|
||||||
lignes: List[LigneCommande]
|
lignes: List[LigneCommande]
|
||||||
reference: Optional[str] = None # Référence externe
|
reference: Optional[str] = None
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
json_schema_extra = {
|
json_schema_extra = {
|
||||||
|
|
@ -629,6 +637,8 @@ class CommandeUpdateRequest(BaseModel):
|
||||||
"""Modification d'une commande existante"""
|
"""Modification d'une commande existante"""
|
||||||
|
|
||||||
date_commande: Optional[date] = None
|
date_commande: Optional[date] = None
|
||||||
|
date_livraison: Optional[date] = None
|
||||||
|
date_expedition: Optional[date] = None
|
||||||
lignes: Optional[List[LigneCommande]] = None
|
lignes: Optional[List[LigneCommande]] = None
|
||||||
statut: Optional[int] = Field(None, ge=0, le=6)
|
statut: Optional[int] = Field(None, ge=0, le=6)
|
||||||
reference: Optional[str] = None
|
reference: Optional[str] = None
|
||||||
|
|
@ -637,6 +647,8 @@ class CommandeUpdateRequest(BaseModel):
|
||||||
json_schema_extra = {
|
json_schema_extra = {
|
||||||
"example": {
|
"example": {
|
||||||
"date_commande": "2024-01-15",
|
"date_commande": "2024-01-15",
|
||||||
|
"date_livraison": "2024-01-15",
|
||||||
|
"date_expedition": "2024-01-15",
|
||||||
"reference": "CMD-EXT-001",
|
"reference": "CMD-EXT-001",
|
||||||
"lignes": [
|
"lignes": [
|
||||||
{
|
{
|
||||||
|
|
@ -668,6 +680,8 @@ class LivraisonCreateRequest(BaseModel):
|
||||||
|
|
||||||
client_id: str
|
client_id: str
|
||||||
date_livraison: Optional[date] = None
|
date_livraison: Optional[date] = None
|
||||||
|
date_livraison_prevue: Optional[date] = None
|
||||||
|
date_expedition: Optional[date] = None
|
||||||
lignes: List[LigneLivraison]
|
lignes: List[LigneLivraison]
|
||||||
reference: Optional[str] = None
|
reference: Optional[str] = None
|
||||||
|
|
||||||
|
|
@ -693,6 +707,8 @@ class LivraisonUpdateRequest(BaseModel):
|
||||||
"""Modification d'une livraison existante"""
|
"""Modification d'une livraison existante"""
|
||||||
|
|
||||||
date_livraison: Optional[date] = None
|
date_livraison: Optional[date] = None
|
||||||
|
date_livraison_prevue: Optional[date] = None
|
||||||
|
date_expedition: Optional[date] = None
|
||||||
lignes: Optional[List[LigneLivraison]] = None
|
lignes: Optional[List[LigneLivraison]] = None
|
||||||
statut: Optional[int] = Field(None, ge=0, le=6)
|
statut: Optional[int] = Field(None, ge=0, le=6)
|
||||||
reference: Optional[str] = None
|
reference: Optional[str] = None
|
||||||
|
|
@ -700,6 +716,10 @@ class LivraisonUpdateRequest(BaseModel):
|
||||||
class Config:
|
class Config:
|
||||||
json_schema_extra = {
|
json_schema_extra = {
|
||||||
"example": {
|
"example": {
|
||||||
|
"date_livraison": "2024-01-15",
|
||||||
|
"date_livraison_prevue": "2024-01-15",
|
||||||
|
"date_expedition": "2024-01-15",
|
||||||
|
"reference": "BL-EXT-001",
|
||||||
"lignes": [
|
"lignes": [
|
||||||
{
|
{
|
||||||
"article_code": "ART001",
|
"article_code": "ART001",
|
||||||
|
|
@ -730,6 +750,8 @@ class AvoirCreateRequest(BaseModel):
|
||||||
|
|
||||||
client_id: str
|
client_id: str
|
||||||
date_avoir: Optional[date] = None
|
date_avoir: Optional[date] = None
|
||||||
|
date_livraison: Optional[date] = None
|
||||||
|
date_expedition: Optional[date] = None
|
||||||
lignes: List[LigneAvoir]
|
lignes: List[LigneAvoir]
|
||||||
reference: Optional[str] = None
|
reference: Optional[str] = None
|
||||||
|
|
||||||
|
|
@ -755,6 +777,8 @@ class AvoirUpdateRequest(BaseModel):
|
||||||
"""Modification d'un avoir existant"""
|
"""Modification d'un avoir existant"""
|
||||||
|
|
||||||
date_avoir: Optional[date] = None
|
date_avoir: Optional[date] = None
|
||||||
|
date_livraison: Optional[date] = None
|
||||||
|
date_expedition: Optional[date] = None
|
||||||
lignes: Optional[List[LigneAvoir]] = None
|
lignes: Optional[List[LigneAvoir]] = None
|
||||||
statut: Optional[int] = Field(None, ge=0, le=6)
|
statut: Optional[int] = Field(None, ge=0, le=6)
|
||||||
reference: Optional[str] = None
|
reference: Optional[str] = None
|
||||||
|
|
@ -762,6 +786,10 @@ class AvoirUpdateRequest(BaseModel):
|
||||||
class Config:
|
class Config:
|
||||||
json_schema_extra = {
|
json_schema_extra = {
|
||||||
"example": {
|
"example": {
|
||||||
|
"date_avoir": "2024-01-15",
|
||||||
|
"date_livraison": "2024-01-15",
|
||||||
|
"date_expedition": "2024-01-15",
|
||||||
|
"reference": "AV-EXT-001",
|
||||||
"lignes": [
|
"lignes": [
|
||||||
{
|
{
|
||||||
"article_code": "ART001",
|
"article_code": "ART001",
|
||||||
|
|
@ -792,6 +820,8 @@ class FactureCreateRequest(BaseModel):
|
||||||
|
|
||||||
client_id: str
|
client_id: str
|
||||||
date_facture: Optional[date] = None
|
date_facture: Optional[date] = None
|
||||||
|
date_livraison: Optional[date] = None
|
||||||
|
date_expedition: Optional[date] = None
|
||||||
lignes: List[LigneFacture]
|
lignes: List[LigneFacture]
|
||||||
reference: Optional[str] = None
|
reference: Optional[str] = None
|
||||||
|
|
||||||
|
|
@ -817,6 +847,8 @@ class FactureUpdateRequest(BaseModel):
|
||||||
"""Modification d'une facture existante"""
|
"""Modification d'une facture existante"""
|
||||||
|
|
||||||
date_facture: Optional[date] = None
|
date_facture: Optional[date] = None
|
||||||
|
date_livraison: Optional[date] = None
|
||||||
|
date_expedition: Optional[date] = None
|
||||||
lignes: Optional[List[LigneFacture]] = None
|
lignes: Optional[List[LigneFacture]] = None
|
||||||
statut: Optional[int] = Field(None, ge=0, le=6)
|
statut: Optional[int] = Field(None, ge=0, le=6)
|
||||||
reference: Optional[str] = None
|
reference: Optional[str] = None
|
||||||
|
|
@ -824,6 +856,9 @@ class FactureUpdateRequest(BaseModel):
|
||||||
class Config:
|
class Config:
|
||||||
json_schema_extra = {
|
json_schema_extra = {
|
||||||
"example": {
|
"example": {
|
||||||
|
"date_facture": "2024-01-15",
|
||||||
|
"date_livraison": "2024-01-15",
|
||||||
|
"date_expedition": "2024-01-15",
|
||||||
"lignes": [
|
"lignes": [
|
||||||
{
|
{
|
||||||
"article_code": "ART001",
|
"article_code": "ART001",
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,6 @@ logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class SageGatewayClient:
|
class SageGatewayClient:
|
||||||
"""
|
|
||||||
Client HTTP pour communiquer avec la gateway Sage Windows
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.url = settings.sage_gateway_url.rstrip("/")
|
self.url = settings.sage_gateway_url.rstrip("/")
|
||||||
self.headers = {
|
self.headers = {
|
||||||
|
|
@ -264,9 +260,6 @@ class SageGatewayClient:
|
||||||
"""Lecture d'une livraison avec ses lignes"""
|
"""Lecture d'une livraison avec ses lignes"""
|
||||||
return self._post("/sage/livraisons/get", {"code": numero}).get("data")
|
return self._post("/sage/livraisons/get", {"code": numero}).get("data")
|
||||||
|
|
||||||
# =====================================================
|
|
||||||
# CACHE (ADMIN)
|
|
||||||
# =====================================================
|
|
||||||
def refresh_cache(self) -> Dict:
|
def refresh_cache(self) -> Dict:
|
||||||
"""Force le rafraîchissement du cache Windows"""
|
"""Force le rafraîchissement du cache Windows"""
|
||||||
return self._post("/sage/cache/refresh")
|
return self._post("/sage/cache/refresh")
|
||||||
|
|
@ -275,9 +268,6 @@ class SageGatewayClient:
|
||||||
"""Récupère les infos du cache Windows"""
|
"""Récupère les infos du cache Windows"""
|
||||||
return self._get("/sage/cache/info").get("data", {})
|
return self._get("/sage/cache/info").get("data", {})
|
||||||
|
|
||||||
# =====================================================
|
|
||||||
# HEALTH
|
|
||||||
# =====================================================
|
|
||||||
def health(self) -> dict:
|
def health(self) -> dict:
|
||||||
"""Health check de la gateway Windows"""
|
"""Health check de la gateway Windows"""
|
||||||
try:
|
try:
|
||||||
|
|
@ -336,12 +326,11 @@ class SageGatewayClient:
|
||||||
try:
|
try:
|
||||||
logger.info(f"📄 Demande génération PDF: doc_id={doc_id}, type={type_doc}")
|
logger.info(f"📄 Demande génération PDF: doc_id={doc_id}, type={type_doc}")
|
||||||
|
|
||||||
# Appel HTTP vers la gateway Windows
|
|
||||||
r = requests.post(
|
r = requests.post(
|
||||||
f"{self.url}/sage/documents/generate-pdf",
|
f"{self.url}/sage/documents/generate-pdf",
|
||||||
json={"doc_id": doc_id, "type_doc": type_doc},
|
json={"doc_id": doc_id, "type_doc": type_doc},
|
||||||
headers=self.headers,
|
headers=self.headers,
|
||||||
timeout=60, # Timeout élevé pour génération PDF
|
timeout=60,
|
||||||
)
|
)
|
||||||
|
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
|
|
@ -350,7 +339,6 @@ class SageGatewayClient:
|
||||||
|
|
||||||
response_data = r.json()
|
response_data = r.json()
|
||||||
|
|
||||||
# Vérifier que la réponse contient bien le PDF
|
|
||||||
if not response_data.get("success"):
|
if not response_data.get("success"):
|
||||||
error_msg = response_data.get("error", "Erreur inconnue")
|
error_msg = response_data.get("error", "Erreur inconnue")
|
||||||
raise RuntimeError(f"Gateway a retourné une erreur: {error_msg}")
|
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})"
|
f"PDF vide retourné par la gateway pour {doc_id} (type {type_doc})"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Décoder le base64
|
|
||||||
pdf_bytes = base64.b64decode(pdf_base64)
|
pdf_bytes = base64.b64decode(pdf_base64)
|
||||||
|
|
||||||
logger.info(f"✅ PDF décodé: {len(pdf_bytes)} octets")
|
logger.info(f"✅ PDF décodé: {len(pdf_bytes)} octets")
|
||||||
|
|
@ -410,15 +397,12 @@ class SageGatewayClient:
|
||||||
def get_stats_familles(self) -> Dict:
|
def get_stats_familles(self) -> Dict:
|
||||||
return self._get("/sage/familles/stats").get("data", {})
|
return self._get("/sage/familles/stats").get("data", {})
|
||||||
|
|
||||||
|
|
||||||
def creer_entree_stock(self, entree_data: Dict) -> Dict:
|
def creer_entree_stock(self, entree_data: Dict) -> Dict:
|
||||||
return self._post("/sage/stock/entree", entree_data).get("data", {})
|
return self._post("/sage/stock/entree", entree_data).get("data", {})
|
||||||
|
|
||||||
|
|
||||||
def creer_sortie_stock(self, sortie_data: Dict) -> Dict:
|
def creer_sortie_stock(self, sortie_data: Dict) -> Dict:
|
||||||
return self._post("/sage/stock/sortie", sortie_data).get("data", {})
|
return self._post("/sage/stock/sortie", sortie_data).get("data", {})
|
||||||
|
|
||||||
|
|
||||||
def lire_mouvement_stock(self, numero: str) -> Optional[Dict]:
|
def lire_mouvement_stock(self, numero: str) -> Optional[Dict]:
|
||||||
try:
|
try:
|
||||||
response = self._get(f"/sage/stock/mouvement/{numero}")
|
response = self._get(f"/sage/stock/mouvement/{numero}")
|
||||||
|
|
@ -427,14 +411,11 @@ class SageGatewayClient:
|
||||||
logger.error(f"Erreur lecture mouvement {numero}: {e}")
|
logger.error(f"Erreur lecture mouvement {numero}: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def lister_modeles_disponibles(self) -> Dict:
|
def lister_modeles_disponibles(self) -> Dict:
|
||||||
"""Liste les modèles Crystal Reports disponibles"""
|
"""Liste les modèles Crystal Reports disponibles"""
|
||||||
try:
|
try:
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
f"{self.url}/sage/modeles/list",
|
f"{self.url}/sage/modeles/list", headers=self.headers, timeout=30
|
||||||
headers=self.headers,
|
|
||||||
timeout=30
|
|
||||||
)
|
)
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
return r.json().get("data", {})
|
return r.json().get("data", {})
|
||||||
|
|
@ -442,26 +423,11 @@ class SageGatewayClient:
|
||||||
logger.error(f"❌ Erreur listage modèles: {e}")
|
logger.error(f"❌ Erreur listage modèles: {e}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
def generer_pdf_document(
|
def generer_pdf_document(
|
||||||
self,
|
self, numero: str, type_doc: int, modele: str = None, base64_encode: bool = True
|
||||||
numero: str,
|
|
||||||
type_doc: int,
|
|
||||||
modele: str = None,
|
|
||||||
base64_encode: bool = True
|
|
||||||
) -> Union[bytes, str, Dict]:
|
) -> 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:
|
try:
|
||||||
params = {
|
params = {"type_doc": type_doc, "base64_encode": base64_encode}
|
||||||
"type_doc": type_doc,
|
|
||||||
"base64_encode": base64_encode
|
|
||||||
}
|
|
||||||
|
|
||||||
if modele:
|
if modele:
|
||||||
params["modele"] = modele
|
params["modele"] = modele
|
||||||
|
|
@ -470,7 +436,7 @@ class SageGatewayClient:
|
||||||
f"{self.url}/sage/documents/{numero}/pdf",
|
f"{self.url}/sage/documents/{numero}/pdf",
|
||||||
params=params,
|
params=params,
|
||||||
headers=self.headers,
|
headers=self.headers,
|
||||||
timeout=60 # PDF peut prendre du temps
|
timeout=60,
|
||||||
)
|
)
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue