chore: refacto

This commit is contained in:
2026-04-20 19:41:52 +02:00
parent 5fc52c72ee
commit 2e9827af98
46 changed files with 497 additions and 648 deletions
+110 -106
View File
@@ -52,10 +52,9 @@ type basketItem struct {
func (d *Database) fetchBasketItems(username string) ([]basketItem, float64, error) {
var items []basketItem
if err := d.GDB.Raw(`SELECT product_id, quantity, price FROM baskets WHERE username = ?`, username).Scan(&items).Error; err != nil {
if err := d.GDB.Table("baskets").Select("product_id, quantity, price").Where("username = ?", username).Scan(&items).Error; err != nil {
return nil, 0, fmt.Errorf("erreur récupération panier: %w", err)
}
total := 0.0
for _, item := range items {
total += item.Price
@@ -84,12 +83,10 @@ func validateCommandStatus(status string) error {
}
func (d *Database) CreateCommand(username string) (*models.Command, error) {
var addrResult struct {
Username string `gorm:"column:username"`
}
adresse := "Adresse non spécifiée"
if err := d.GDB.Raw(`SELECT username FROM clients WHERE username = ?`, username).Scan(&addrResult).Error; err == nil && addrResult.Username != "" {
adresse = addrResult.Username
var clientCheck models.Client
if err := d.GDB.Select("username").Where("username = ?", username).First(&clientCheck).Error; err == nil && clientCheck.Username != "" {
adresse = clientCheck.Username
}
basketItems, totalPrix, err := d.fetchBasketItems(username)
@@ -102,14 +99,15 @@ func (d *Database) CreateCommand(username string) (*models.Command, error) {
}
var cmdResult struct {
ID int `gorm:"column:id"`
CreatedAt time.Time `gorm:"column:created_at"`
UpdatedAt time.Time `gorm:"column:updated_at"`
ID int `gorm:"column:id"`
ClientOrderID int `gorm:"column:client_order_id"`
CreatedAt time.Time `gorm:"column:created_at"`
UpdatedAt time.Time `gorm:"column:updated_at"`
}
err = d.GDB.Raw(`
INSERT INTO commandes (username, status, adresse, total_prix, client_order_id, created_at, updated_at)
VALUES (?, ?, ?, ?, (SELECT COALESCE(MAX(client_order_id), 0) + 1 FROM commandes WHERE username = ?), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
RETURNING id, created_at, updated_at`,
RETURNING id, client_order_id, created_at, updated_at`,
username, "pending", adresse, totalPrix, username).Scan(&cmdResult).Error
if err != nil {
return nil, fmt.Errorf("erreur lors de la création de la commande: %w", err)
@@ -123,12 +121,17 @@ func (d *Database) CreateCommand(username string) (*models.Command, error) {
productName = "Produit inconnu"
}
if err := d.GDB.Exec(`
INSERT INTO command_items (command_id, produit, product_id, quantite, prix)
VALUES (?, ?, ?, ?, ?)`,
commandID, productName, item.ProductID, item.Quantity, item.Price).Error; err != nil {
cmdItem := models.CommandItem{
CommandID: commandID,
Produit: productName,
ProductID: item.ProductID,
Quantity: item.Quantity,
Price: item.Price,
}
if err := d.GDB.Create(&cmdItem).Error; err != nil {
return nil, fmt.Errorf("erreur lors de l'insertion des items: %w", err)
}
}
if err := d.GDB.Exec(`DELETE FROM baskets WHERE username = ?`, username).Error; err != nil {
@@ -136,9 +139,10 @@ func (d *Database) CreateCommand(username string) (*models.Command, error) {
}
command := &models.Command{
ID: commandID,
Status: "pending",
Total: totalPrix,
ID: commandID,
ClientOrderID: cmdResult.ClientOrderID,
Status: "pending",
Total: totalPrix,
}
return command, nil
@@ -188,14 +192,15 @@ func (d *Database) CreateCommandWithAddress(username, deliveryAddress string) (*
}
var cmdResult struct {
ID int `gorm:"column:id"`
CreatedAt time.Time `gorm:"column:created_at"`
UpdatedAt time.Time `gorm:"column:updated_at"`
ID int `gorm:"column:id"`
ClientOrderID int `gorm:"column:client_order_id"`
CreatedAt time.Time `gorm:"column:created_at"`
UpdatedAt time.Time `gorm:"column:updated_at"`
}
err = d.GDB.Raw(`
INSERT INTO commandes (username, status, adresse, total_prix, client_order_id, created_at, updated_at)
VALUES (?, ?, ?, ?, (SELECT COALESCE(MAX(client_order_id), 0) + 1 FROM commandes WHERE username = ?), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
RETURNING id, created_at, updated_at`,
RETURNING id, client_order_id, created_at, updated_at`,
username, "pending", deliveryAddress, totalPrix, username).Scan(&cmdResult).Error
if err != nil {
return nil, fmt.Errorf("erreur création commande: %w", err)
@@ -226,7 +231,7 @@ func (d *Database) CreateCommandWithAddress(username, deliveryAddress string) (*
return nil, fmt.Errorf("erreur insertion items: %w", err)
}
result := d.GDB.Exec(`UPDATE products SET stock = stock - ? WHERE id = ? AND stock >= ?`, item.Quantity, item.ProductID, item.Quantity)
result := d.GDB.Model(&models.Product{}).Where("id = ? AND stock >= ?", item.ProductID, item.Quantity).UpdateColumn("stock", gorm.Expr("stock - ?", item.Quantity))
if result.Error != nil {
log.Printf("⚠️ Erreur décrémentation stock produit %d: %v", item.ProductID, result.Error)
return nil, fmt.Errorf("erreur mise à jour stock: %w", result.Error)
@@ -236,7 +241,7 @@ func (d *Database) CreateCommandWithAddress(username, deliveryAddress string) (*
}
}
if err := d.GDB.Exec(`DELETE FROM baskets WHERE username = ?`, username).Error; err != nil {
if err := d.GDB.Delete(&models.Panier{}, "username = ?", username).Error; err != nil {
log.Printf("⚠️ Erreur vidage panier: %v", err)
}
@@ -248,6 +253,7 @@ func (d *Database) CreateCommandWithAddress(username, deliveryAddress string) (*
command := &models.Command{
ID: commandID,
ClientOrderID: cmdResult.ClientOrderID,
Username: username,
Status: "pending",
Total: totalPrix,
@@ -272,44 +278,37 @@ func (d *Database) GetAllCommands(status, username string) ([]map[string]any, er
}
}
query := `SELECT c.id, c.username, c.status, c.adresse, c.total_prix,
c.livreur_assign, c.created_at, c.updated_at,
c.proposed_address, c.address_proposal_status,
c.client_order_id AS client_order_number
FROM commandes c
WHERE 1=1`
var rows []struct {
ID int `gorm:"column:id"`
Username string `gorm:"column:username"`
Status string `gorm:"column:status"`
Adresse string `gorm:"column:adresse"`
TotalPrix float64 `gorm:"column:total_prix"`
LivreurAssign *string `gorm:"column:livreur_assign"`
CreatedAt time.Time `gorm:"column:created_at"`
UpdatedAt time.Time `gorm:"column:updated_at"`
ProposedAddress *string `gorm:"column:proposed_address"`
AddressProposalStatus string `gorm:"column:address_proposal_status"`
ClientOrderNumber int `gorm:"column:client_order_number"`
}
args := []interface{}{}
gdb := d.GDB.Table("commandes c").
Select(`c.id, c.username, c.status, c.adresse, c.total_prix,
c.livreur_assign, c.created_at, c.updated_at,
c.proposed_address, c.address_proposal_status,
c.client_order_id AS client_order_number`)
if status == "" {
query += ` AND c.status IN ('pending', 'assigned', 'en_route', 'arrived', 'livre')`
gdb = gdb.Where("c.status IN ?", []string{"pending", "assigned", "en_route", "arrived", "livre"})
} else {
query += ` AND c.status = ?`
args = append(args, status)
gdb = gdb.Where("c.status = ?", status)
}
if username != "" {
query += ` AND c.username = ?`
args = append(args, username)
gdb = gdb.Where("c.username = ?", username)
}
query += " ORDER BY c.created_at DESC LIMIT 1000"
var rows []struct {
ID int `gorm:"column:id"`
Username string `gorm:"column:username"`
Status string `gorm:"column:status"`
Adresse string `gorm:"column:adresse"`
TotalPrix float64 `gorm:"column:total_prix"`
LivreurAssign *string `gorm:"column:livreur_assign"`
CreatedAt time.Time `gorm:"column:created_at"`
UpdatedAt time.Time `gorm:"column:updated_at"`
ProposedAddress *string `gorm:"column:proposed_address"`
AddressProposalStatus string `gorm:"column:address_proposal_status"`
ClientOrderNumber int `gorm:"column:client_order_number"`
}
if err := d.GDB.Raw(query, args...).Scan(&rows).Error; err != nil {
if err := gdb.Order("c.created_at DESC").Limit(1000).Scan(&rows).Error; err != nil {
return nil, fmt.Errorf("erreur lors de la récupération des commandes: %w", err)
}
@@ -346,14 +345,11 @@ func (d *Database) GetAllCommands(status, username string) ([]map[string]any, er
}
func (d *Database) GetCommandCount() (int, error) {
var result struct {
Count int `gorm:"column:count"`
}
err := d.GDB.Raw("SELECT COUNT(*) as count FROM commandes").Scan(&result).Error
if err != nil {
var count int64
if err := d.GDB.Model(&models.Command{}).Count(&count).Error; err != nil {
return 0, fmt.Errorf("erreur récupération count commandes: %w", err)
}
return result.Count, nil
return int(count), nil
}
func (d *Database) SetCommandReferralUsed(commandID int, amount float64) error {
@@ -362,26 +358,28 @@ func (d *Database) SetCommandReferralUsed(commandID int, amount float64) error {
func (d *Database) GetCommandByID(id int) (map[string]any, error) {
var row struct {
ID int `gorm:"column:id"`
Username string `gorm:"column:username"`
Status string `gorm:"column:status"`
Adresse string `gorm:"column:adresse"`
TotalPrix float64 `gorm:"column:total_prix"`
LivreurAssign *string `gorm:"column:livreur_assign"`
CreatedAt time.Time `gorm:"column:created_at"`
UpdatedAt time.Time `gorm:"column:updated_at"`
ProposedAddress *string `gorm:"column:proposed_address"`
AddressProposalStatus string `gorm:"column:address_proposal_status"`
ReferralUsed float64 `gorm:"column:referral_used"`
ClientOrderNumber int `gorm:"column:client_order_number"`
ID int `gorm:"column:id"`
Username string `gorm:"column:username"`
Status string `gorm:"column:status"`
Adresse string `gorm:"column:adresse"`
TotalPrix float64 `gorm:"column:total_prix"`
LivreurAssign *string `gorm:"column:livreur_assign"`
CreatedAt time.Time `gorm:"column:created_at"`
UpdatedAt time.Time `gorm:"column:updated_at"`
ProposedAddress *string `gorm:"column:proposed_address"`
AddressProposalStatus string `gorm:"column:address_proposal_status"`
ReferralUsed float64 `gorm:"column:referral_used"`
ClientOrderNumber int `gorm:"column:client_order_number"`
CancelReason string `gorm:"column:cancel_reason"`
}
err := d.GDB.Raw(`
SELECT c.id, c.username, c.status, c.adresse, c.total_prix, c.livreur_assign, c.created_at, c.updated_at,
c.proposed_address, c.address_proposal_status, c.referral_used,
c.client_order_id AS client_order_number
FROM commandes c WHERE c.id = ?`, id).Scan(&row).Error
if err != nil {
if err := d.GDB.Table("commandes c").
Select(`c.id, c.username, c.status, c.adresse, c.total_prix, c.livreur_assign,
c.created_at, c.updated_at, c.proposed_address, c.address_proposal_status,
c.referral_used, c.client_order_id AS client_order_number,
COALESCE(c.cancel_reason, '') AS cancel_reason`).
Where("c.id = ?", id).
First(&row).Error; err != nil {
return nil, fmt.Errorf("erreur lors de la récupération de la commande: %w", err)
}
if row.ID == 0 {
@@ -399,6 +397,7 @@ func (d *Database) GetCommandByID(id int) (map[string]any, error) {
"address_proposal_status": row.AddressProposalStatus,
"referral_used": row.ReferralUsed,
"client_order_number": row.ClientOrderNumber,
"cancel_reason": row.CancelReason,
}
if row.LivreurAssign != nil {
@@ -416,12 +415,23 @@ func (d *Database) GetCommandByID(id int) (map[string]any, error) {
return command, nil
}
// GetClientOrderID retourne le client_order_id (numéro perso du client) pour un commandID global.
// Retourne commandID en fallback si introuvable.
func (d *Database) GetClientOrderID(commandID int) int {
var result struct {
ClientOrderID int `gorm:"column:client_order_id"`
}
if err := d.GDB.Model(&models.Command{}).Select("client_order_id").Where("id = ?", commandID).First(&result).Error; err != nil || result.ClientOrderID == 0 {
return commandID
}
return result.ClientOrderID
}
func (d *Database) GetCommandAddress(commandID int) (string, error) {
var result struct {
Adresse string `gorm:"column:adresse"`
}
err := d.GDB.Raw(`SELECT adresse FROM commandes WHERE id = ?`, commandID).Scan(&result).Error
if err != nil {
if err := d.GDB.Model(&models.Command{}).Select("adresse").Where("id = ?", commandID).First(&result).Error; err != nil {
return "", fmt.Errorf("erreur lors de la récupération de l'adresse: %w", err)
}
if result.Adresse == "" {
@@ -439,9 +449,10 @@ func (d *Database) UpdateCommandAddress(commandID int, deliveryAddress string) e
return fmt.Errorf("adresse vide non autorisée")
}
result := d.GDB.Exec(`
UPDATE commandes SET adresse = ?, updated_at = CURRENT_TIMESTAMP
WHERE id = ?`, deliveryAddress, commandID)
result := d.GDB.Model(&models.Command{}).Where("id = ?", commandID).Updates(map[string]any{
"adresse": deliveryAddress,
"updated_at": time.Now(),
})
if result.Error != nil {
return fmt.Errorf("erreur lors de la mise à jour de l'adresse: %w", result.Error)
}
@@ -459,10 +470,11 @@ func (d *Database) ProposeAddressChange(commandID int, proposedAddress, proposed
return err
}
result := d.GDB.Exec(`
UPDATE commandes
SET proposed_address = ?, address_proposal_status = 'pending', updated_at = CURRENT_TIMESTAMP
WHERE id = ?`, proposedAddress, commandID)
result := d.GDB.Model(&models.Command{}).Where("id = ?", commandID).Updates(map[string]any{
"proposed_address": proposedAddress,
"address_proposal_status": "pending",
"updated_at": time.Now(),
})
if result.Error != nil {
return fmt.Errorf("erreur proposition adresse: %w", result.Error)
}
@@ -519,7 +531,10 @@ func (d *Database) UpdateCommandStatus(commandID int, status string) error {
return err
}
result := d.GDB.Exec(`UPDATE commandes SET status = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?`, status, commandID)
result := d.GDB.Model(&models.Command{}).Where("id = ?", commandID).Updates(map[string]any{
"status": status,
"updated_at": time.Now(),
})
if result.Error != nil {
return fmt.Errorf("erreur lors de la mise à jour du statut: %w", result.Error)
}
@@ -534,10 +549,12 @@ func (d *Database) AddCommandLog(commandID int, status, message, author string)
sanitizedMessage := sanitizeLogMessage(message)
sanitizedAuthor := sanitizeLogMessage(author)
if err := d.GDB.Exec(`
INSERT INTO command_logs (command_id, status, message, author, created_at)
VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP)`,
commandID, status, sanitizedMessage, sanitizedAuthor).Error; err != nil {
if err := d.GDB.Create(&models.CommandLog{
CommandID: commandID,
Status: status,
Message: sanitizedMessage,
Author: sanitizedAuthor,
}).Error; err != nil {
log.Printf("⚠️ Avertissement: impossible d'ajouter le log (table command_logs peut-être manquante): %v", err)
return nil
}
@@ -547,22 +564,9 @@ func (d *Database) AddCommandLog(commandID int, status, message, author string)
// GetCommandLogs récupère tous les logs d'une commande
func (d *Database) GetCommandLogs(commandID int) ([]map[string]any, error) {
var rows []struct {
ID int `gorm:"column:id"`
CommandID int `gorm:"column:command_id"`
Status string `gorm:"column:status"`
Message string `gorm:"column:message"`
Author string `gorm:"column:author"`
CreatedAt time.Time `gorm:"column:created_at"`
}
var rows []models.CommandLog
err := d.GDB.Raw(`
SELECT id, command_id, status, message, author, created_at
FROM command_logs
WHERE command_id = ?
ORDER BY created_at ASC`, commandID).Scan(&rows).Error
if err != nil {
// Si la table n'existe pas, retourner un tableau vide au lieu d'une erreur
if err := d.GDB.Where("command_id = ?", commandID).Order("created_at ASC").Find(&rows).Error; err != nil {
log.Printf("⚠️ Avertissement: impossible de récupérer les logs: %v", err)
return []map[string]any{}, nil
}