chore: fix prices

This commit is contained in:
2026-03-02 03:28:45 +01:00
parent e7a6dc2230
commit 6c8af9acd4
10 changed files with 266 additions and 41 deletions
+91 -11
View File
@@ -10,9 +10,9 @@ import (
// AddProductInBasket ajoute un produit au panier de l'utilisateur
func (d *Database) AddProductInBasket(username, nameProduct string, quantity float64, category string) (*models.Panier, error) {
// Rechercher le produit par son nom et catégorie
// Rechercher le produit par son nom et catégorie (case-insensitive)
var productID int
productQuery := `SELECT id FROM products WHERE name = $1 AND category = $2`
productQuery := `SELECT id FROM products WHERE LOWER(name) = LOWER($1) AND LOWER(category) = LOWER($2)`
err := d.QueryRow(productQuery, nameProduct, category).Scan(&productID)
if err == sql.ErrNoRows {
return nil, fmt.Errorf("produit '%s' non trouvé dans la catégorie '%s'", nameProduct, category)
@@ -29,18 +29,19 @@ func (d *Database) AddProductInBasket(username, nameProduct string, quantity flo
// Vérifier si le produit existe déjà dans le panier
var existingID int
var existingQuantity float64
checkQuery := `SELECT id, quantity FROM baskets WHERE username = $1 AND product_id = $2`
err = d.QueryRow(checkQuery, username, productID).Scan(&existingID, &existingQuantity)
var existingQuantity, existingPrice float64
checkQuery := `SELECT id, quantity, price FROM baskets WHERE username = $1 AND product_id = $2`
err = d.QueryRow(checkQuery, username, productID).Scan(&existingID, &existingQuantity, &existingPrice)
if err == nil {
// Produit déjà dans le panier : mettre à jour quantité et prix
// Produit déjà dans le panier : cumuler quantité et prix total de la ligne
newQuantity := existingQuantity + quantity
newPrice := existingPrice + price
updateQuery := `UPDATE baskets SET quantity = $1, price = $2, created_at = CURRENT_TIMESTAMP
WHERE id = $3 RETURNING id, username, product_id, quantity, price, created_at`
var basket models.Panier
err = d.QueryRow(updateQuery, newQuantity, price, existingID).Scan(
err = d.QueryRow(updateQuery, newQuantity, newPrice, existingID).Scan(
&basket.ID,
&basket.Username,
&basket.ProductID,
@@ -75,7 +76,85 @@ func (d *Database) AddProductInBasket(username, nameProduct string, quantity flo
return &basket, nil
}
// GetProductPrice récupère le prix réel d'un produit pour une quantité donnée
// GetProductPriceByID récupère le prix d'un produit par son ID et quantité (NUMERIC exact)
func (d *Database) GetProductPriceByID(productID int, quantity float64) (float64, error) {
var price float64
// Comparaison NUMERIC précise : évite les problèmes float64 vs NUMERIC(10,3)
exactQuery := `
SELECT price FROM product_prices
WHERE product_id = $1 AND quantity = ROUND($2::NUMERIC, 3)
LIMIT 1
`
err := d.QueryRow(exactQuery, productID, quantity).Scan(&price)
if err == nil {
return price, nil
}
// Fallback : palier inférieur le plus proche
tierQuery := `
SELECT price FROM product_prices
WHERE product_id = $1 AND quantity <= ROUND($2::NUMERIC, 3)
ORDER BY quantity DESC LIMIT 1
`
err = d.QueryRow(tierQuery, productID, quantity).Scan(&price)
if err != nil {
return 0, fmt.Errorf("aucun prix trouvé pour product_id=%d qty=%.3f: %w", productID, quantity, err)
}
return price, nil
}
// GetProductStockByID récupère le stock d'un produit par son ID
func (d *Database) GetProductStockByID(productID int) (float64, error) {
var stock float64
err := d.QueryRow(`SELECT stock FROM products WHERE id = $1`, productID).Scan(&stock)
if err != nil {
return 0, fmt.Errorf("produit %d non trouvé: %w", productID, err)
}
return stock, nil
}
// AddProductInBasketByID ajoute un produit au panier en utilisant son ID directement
func (d *Database) AddProductInBasketByID(username string, productID int, quantity float64) (*models.Panier, error) {
price, err := d.GetProductPriceByID(productID, quantity)
if err != nil {
return nil, fmt.Errorf("erreur récupération prix: %w", err)
}
var existingID int
var existingQuantity, existingPrice float64
checkQuery := `SELECT id, quantity, price FROM baskets WHERE username = $1 AND product_id = $2`
err = d.QueryRow(checkQuery, username, productID).Scan(&existingID, &existingQuantity, &existingPrice)
if err == nil {
newQuantity := existingQuantity + quantity
newPrice := existingPrice + price
updateQuery := `UPDATE baskets SET quantity = $1, price = $2, created_at = CURRENT_TIMESTAMP
WHERE id = $3 RETURNING id, username, product_id, quantity, price, created_at`
var basket models.Panier
err = d.QueryRow(updateQuery, newQuantity, newPrice, existingID).Scan(
&basket.ID, &basket.Username, &basket.ProductID, &basket.Quantity, &basket.Price, &basket.CreatedAt,
)
if err != nil {
return nil, fmt.Errorf("erreur lors de la mise à jour du panier: %w", err)
}
return &basket, nil
}
insertQuery := `INSERT INTO baskets (username, product_id, quantity, price, created_at)
VALUES ($1, $2, $3, $4, CURRENT_TIMESTAMP)
RETURNING id, username, product_id, quantity, price, created_at`
var basket models.Panier
err = d.QueryRow(insertQuery, username, productID, quantity, price).Scan(
&basket.ID, &basket.Username, &basket.ProductID, &basket.Quantity, &basket.Price, &basket.CreatedAt,
)
if err != nil {
return nil, fmt.Errorf("erreur lors de l'ajout au panier: %w", err)
}
return &basket, nil
}
// GetProductPrice récupère le prix réel d'un produit pour une quantité donnée (legacy)
func (d *Database) GetProductPrice(name, category string, quantity float64) (float64, error) {
var price float64
@@ -100,7 +179,7 @@ func (d *Database) GetProductPrice(name, category string, quantity float64) (flo
func (d *Database) GetProductStock(name, category string) (float64, error) {
var stock float64
query := `SELECT stock FROM products WHERE name = $1 AND category = $2`
query := `SELECT stock FROM products WHERE LOWER(name) = LOWER($1) AND LOWER(category) = LOWER($2)`
err := d.QueryRow(query, name, category).Scan(&stock)
if err != nil {
return 0, fmt.Errorf("produit non trouvé: %w", err)
@@ -109,7 +188,7 @@ func (d *Database) GetProductStock(name, category string) (float64, error) {
}
func (d *Database) DecrementProductStock(name, category string, quantity float64) error {
query := `UPDATE products SET stock = stock - $1 WHERE name = $2 AND category = $3 AND stock >= $1`
query := `UPDATE products SET stock = stock - $1 WHERE LOWER(name) = LOWER($2) AND LOWER(category) = LOWER($3) AND stock >= $1`
result, err := d.Exec(query, quantity, name, category)
if err != nil {
return fmt.Errorf("erreur mise à jour stock: %w", err)
@@ -223,8 +302,9 @@ func (d *Database) ClearBasket(username string) error {
}
// GetBasketTotal calcule le montant total du panier d'un utilisateur
// price dans baskets = prix total de la ligne (cumul des ajouts)
func (d *Database) GetBasketTotal(username string) (float64, error) {
query := `SELECT COALESCE(SUM(quantity * price), 0) as total
query := `SELECT COALESCE(SUM(price), 0) as total
FROM baskets
WHERE username = $1`