Fournisseur : repli sur l'API FF pour les articles absents de la base miroir

Les articles récents (503996, 504022, 504025, 505349…) n'ont aucune ligne
artfou1 dans la recopie FF : ni référence, ni fournisseur. Le Hit Parade
et les pages Stock les affichaient en « Sans fournisseur ».

Les lignes restées « Sans fournisseur » après la requête SQL sont
complétées par l'API FF en direct, avec la règle du tableau de bord :
fournisseur de la dernière entrée en stock, sinon celui du référentiel.
Au plus 200 articles par chargement (12 en parallèle), réponses gardées
en mémoire le temps du cache FF pour ne pas réinterroger l'API à chaque
onglet.

Le test d'intégration sert une fausse API FF et vérifie que l'article
absent de la base est complété ; il échoue sans le repli.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DhSZx8CCuqoKrDw7unFqGq
This commit is contained in:
Claude committed 2026-10-19 20:12:18 +00:00
1 parent 0f782d3fc9
commit 358cf0643f
3 files changed
+150 -5

No files matched your search

+17 -5
View File
@@ -7,7 +7,7 @@ use super::api::{avec_cle_ff, get_ff_api_base};
use super::cache::get_fournisseurs_cached;
use super::js::{get, js_number, js_number_to_string, message_erreur};
use super::pg::{
pg_get_ca_by_fournisseur, pg_get_ca_by_nomenclature, pg_get_commandes_auto, pg_get_dashboard_data, pg_get_hit_parade,
completer_fournisseurs, pg_get_ca_by_fournisseur, pg_get_ca_by_nomenclature, pg_get_commandes_auto, pg_get_dashboard_data, pg_get_hit_parade,
pg_get_sans_vente_6_mois, pg_get_stock_negatif, pg_get_stock_sans_vente, PgCommandeAutoRow,
};
use crate::error::{AppError, AppResult};
@@ -115,7 +115,9 @@ pub async fn page_hit_parade(ctx: Ctx) -> AppResult<Value> {
let (d, f) = (date_debut.clone(), date_fin.clone());
match cached(&format!("hit-parade:{date_debut}:{date_fin}"), CacheOpts::default(), move || async move {
pg_get_hit_parade(&d, &f).await
let mut rows = pg_get_hit_parade(&d, &f).await?;
completer_fournisseurs(&mut rows, |r| (r.codein.as_str(), &mut r.fournisseur)).await;
anyhow::Ok(rows)
})
.await
{
@@ -142,10 +144,20 @@ pub async fn page_stock_negatif(ctx: Ctx) -> AppResult<Value> {
let (k1, k2, k3) =
(format!("stock-negatif:{magasin}"), format!("stock-sans-vente:{magasin}"), format!("stock-sans-vente-6-mois:{magasin}"));
let res = tokio::try_join!(
cached(&k1, CacheOpts::default(), move || async move { pg_get_stock_negatif(s1.as_deref()).await }),
cached(&k2, CacheOpts::default(), move || async move { pg_get_stock_sans_vente(s2.as_deref()).await }),
cached(&k1, CacheOpts::default(), move || async move {
let mut rows = pg_get_stock_negatif(s1.as_deref()).await?;
completer_fournisseurs(&mut rows, |r| (r.codein.as_str(), &mut r.fournisseur)).await;
anyhow::Ok(rows)
}),
cached(&k2, CacheOpts::default(), move || async move {
let mut rows = pg_get_stock_sans_vente(s2.as_deref()).await?;
completer_fournisseurs(&mut rows, |r| (r.codein.as_str(), &mut r.fournisseur)).await;
anyhow::Ok(rows)
}),
cached(&k3, CacheOpts::default(), move || async move {
pg_get_sans_vente_6_mois(s3.as_deref()).await
let mut rows = pg_get_sans_vente_6_mois(s3.as_deref()).await?;
completer_fournisseurs(&mut rows, |r| (r.codein.as_str(), &mut r.fournisseur)).await;
anyhow::Ok(rows)
}),
);
match res {