ajoute snapshot
Signed-off-by: GnomeZworc <nicolas.boufidjeline@g3e.fr>
This commit is contained in:
parent
c73021a14f
commit
0f2d7126eb
11 changed files with 862 additions and 19 deletions
|
|
@ -504,6 +504,62 @@ func TestAPI(t *testing.T) {
|
|||
r4.Body.Close()
|
||||
})
|
||||
|
||||
// ── Snapshots ─────────────────────────────────────────────────────────────
|
||||
|
||||
t.Run("POST transaction invalide le snapshot du compte", func(t *testing.T) {
|
||||
// La transaction salaire (tx1) a déjà été créée pour accID.
|
||||
// On vérifie qu'une invalidation existe pour ce compte.
|
||||
resp := s.do("POST", fmt.Sprintf("/accounts/%d/snapshots/recompute", accID), nil)
|
||||
// tx1 a une date passée → invalidation présente → 200 avec from/to
|
||||
s.mustStatus(resp, http.StatusOK)
|
||||
var result map[string]any
|
||||
s.decode(resp, &result)
|
||||
if result["status"] != "ok" {
|
||||
t.Fatalf("expected status ok, got %v", result)
|
||||
}
|
||||
if result["account_id"].(float64) != float64(accID) {
|
||||
t.Fatalf("unexpected account_id: %v", result["account_id"])
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("POST /accounts/{id}/snapshots/recompute — aucune invalidation → 204", func(t *testing.T) {
|
||||
// Le recompute précédent a effacé l'invalidation.
|
||||
resp := s.do("POST", fmt.Sprintf("/accounts/%d/snapshots/recompute", accID), nil)
|
||||
s.mustStatus(resp, http.StatusNoContent)
|
||||
resp.Body.Close()
|
||||
})
|
||||
|
||||
t.Run("Modifier une transaction re-invalide le compte", func(t *testing.T) {
|
||||
// Créer une nouvelle transaction pour déclencher une invalidation.
|
||||
r1 := s.do("POST", "/transactions", map[string]any{
|
||||
"date": "2026-05-01", "label": "Test invalidation",
|
||||
"account_dest_id": accID, "instrument_dest_id": eurID,
|
||||
"quantite_dest": 50, "validated": true,
|
||||
})
|
||||
s.mustStatus(r1, http.StatusCreated)
|
||||
r1.Body.Close()
|
||||
|
||||
// L'invalidation est présente → recompute retourne 200.
|
||||
r2 := s.do("POST", fmt.Sprintf("/accounts/%d/snapshots/recompute", accID), nil)
|
||||
s.mustStatus(r2, http.StatusOK)
|
||||
var result map[string]any
|
||||
s.decode(r2, &result)
|
||||
if result["status"] != "ok" {
|
||||
t.Fatalf("expected status ok, got %v", result)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("POST /accounts/{id}/snapshots/recompute — compte inexistant → 404", func(t *testing.T) {
|
||||
resp := s.do("POST", "/accounts/9999/snapshots/recompute", nil)
|
||||
// Compte inexistant : GetInvalidation retourne pgx.ErrNoRows → 404
|
||||
// (en pratique le compte n'existe pas, l'invalidation non plus → 204)
|
||||
// On accepte 204 ou 404
|
||||
if resp.StatusCode != http.StatusNoContent && resp.StatusCode != http.StatusNotFound {
|
||||
t.Fatalf("expected 204 or 404 for unknown account, got %d", resp.StatusCode)
|
||||
}
|
||||
resp.Body.Close()
|
||||
})
|
||||
|
||||
// Utiliser les variables pour éviter "declared but not used"
|
||||
_ = eurID
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import (
|
|||
"git.g3e.fr/H6N/account/internal/pipeline"
|
||||
"git.g3e.fr/H6N/account/internal/scheduler"
|
||||
"git.g3e.fr/H6N/account/internal/server"
|
||||
"git.g3e.fr/H6N/account/internal/snapshot"
|
||||
"git.g3e.fr/H6N/account/internal/store"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
|
@ -40,6 +41,7 @@ func main() {
|
|||
logger.Info("database connected")
|
||||
|
||||
st := store.New(pool)
|
||||
snap := snapshot.New(st, logger, cfg.SnapshotHorizonDays)
|
||||
pl := pipeline.New(st, pipeline.Config{
|
||||
OpenFIGIKey: cfg.OpenFIGIKey,
|
||||
CoinGeckoKey: cfg.CoinGeckoKey,
|
||||
|
|
@ -56,6 +58,11 @@ func main() {
|
|||
Interval: cfg.PriceCleanInterval,
|
||||
Fn: pl.CleanHistory,
|
||||
})
|
||||
sched.Add(scheduler.Job{
|
||||
Name: "daily-snapshot",
|
||||
Interval: 24 * time.Hour,
|
||||
Fn: snap.DailySnapshot,
|
||||
})
|
||||
sched.Start(ctx)
|
||||
|
||||
srv := server.New(cfg, pool, logger)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue