chore: refacto
This commit is contained in:
@@ -65,10 +65,14 @@ func (d *Database) CancelCommandAtomic(commandID int, username, reason string, f
|
||||
return fmt.Errorf("confirmation requise")
|
||||
}
|
||||
|
||||
cancelMsg := reason
|
||||
if cancelMsg == "Annulation par le client" {
|
||||
cancelMsg = ""
|
||||
}
|
||||
result := tx.Exec(`
|
||||
UPDATE commandes
|
||||
SET status = 'cancelled', updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ? AND status = ? AND username = ?`, commandID, cmdResult.Status, username)
|
||||
SET status = 'cancelled', cancel_reason = ?, updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ? AND status = ? AND username = ?`, cancelMsg, commandID, cmdResult.Status, username)
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
@@ -87,13 +91,20 @@ func (d *Database) CancelCommandAtomic(commandID int, username, reason string, f
|
||||
log.Printf("✅ [CancelAtomic] Stock remboursé")
|
||||
}
|
||||
|
||||
if err := tx.Exec(`
|
||||
UPDATE clients
|
||||
SET cancellations_count = COALESCE(cancellations_count, 0) + 1,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE username = ?`, username).Error; err != nil {
|
||||
log.Printf("⚠️ [CancelAtomic] Erreur incrémentation count: %v", err)
|
||||
}
|
||||
|
||||
if isLateCancel {
|
||||
log.Printf("⚠️ [CancelAtomic] Annulation tardive confirmée - Application pénalité")
|
||||
penalty, _ = d.CalculateCancellationPenalty(username)
|
||||
if err := tx.Exec(`
|
||||
UPDATE clients
|
||||
SET amende = amende + ?,
|
||||
cancellations_count = COALESCE(cancellations_count, 0) + 1,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE username = ?`, penalty, username).Error; err != nil {
|
||||
log.Printf("❌ [CancelAtomic] Erreur pénalité: %v", err)
|
||||
@@ -250,7 +261,7 @@ func (d *Database) GetCommandPositionInQueue(livreurUsername string, commandID i
|
||||
|
||||
func (d *Database) GetCancelledCommands(username string, limit int) ([]map[string]any, error) {
|
||||
query := `
|
||||
SELECT id, client_order_id AS client_order_number, username, status, adresse, total_prix::float8 as total_prix, created_at, updated_at
|
||||
SELECT id, client_order_id AS client_order_number, username, status, adresse, total_prix::float8 as total_prix, created_at, updated_at, COALESCE(cancel_reason, '') AS cancel_reason
|
||||
FROM commandes
|
||||
WHERE status = 'cancelled'`
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ func (d *Database) UpdateCategory(id int, name, color string, isComingSoon bool)
|
||||
if err := d.GDB.First(&c, id).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := d.GDB.Model(&c).Updates(Category{Name: name, Color: color, IsComingSoon: isComingSoon}).Error; err != nil {
|
||||
if err := d.GDB.Model(&c).Updates(map[string]interface{}{"name": name, "color": color, "is_coming_soon": isComingSoon}).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &c, nil
|
||||
|
||||
@@ -79,20 +79,22 @@ func (d *Database) GetClientByID(id int) (*models.Client, error) {
|
||||
// GetAllClients récupère tous les clients
|
||||
func (d *Database) GetAllClients() ([]*models.Client, error) {
|
||||
var rows []struct {
|
||||
ID int `gorm:"column:id"`
|
||||
Username string `gorm:"column:username"`
|
||||
Password string `gorm:"column:password"`
|
||||
Nom string `gorm:"column:nom"`
|
||||
Prenom string `gorm:"column:prenom"`
|
||||
Telephone string `gorm:"column:telephone"`
|
||||
Command int `gorm:"column:command"`
|
||||
Amende float64 `gorm:"column:amende"`
|
||||
ReferralBalance float64 `gorm:"column:referral_balance"`
|
||||
PointsExtraJSON []byte `gorm:"column:points_extra"`
|
||||
CreatedAt time.Time `gorm:"column:created_at"`
|
||||
ID int `gorm:"column:id"`
|
||||
Username string `gorm:"column:username"`
|
||||
Password string `gorm:"column:password"`
|
||||
Nom string `gorm:"column:nom"`
|
||||
Prenom string `gorm:"column:prenom"`
|
||||
Telephone string `gorm:"column:telephone"`
|
||||
Command int `gorm:"column:command"`
|
||||
Amende float64 `gorm:"column:amende"`
|
||||
ReferralBalance float64 `gorm:"column:referral_balance"`
|
||||
CancellationsCount int `gorm:"column:cancellations_count"`
|
||||
PointsExtraJSON []byte `gorm:"column:points_extra"`
|
||||
CreatedAt time.Time `gorm:"column:created_at"`
|
||||
}
|
||||
err := d.GDB.Raw(`
|
||||
SELECT id, username, password, nom, prenom, telephone, command, amende, referral_balance,
|
||||
COALESCE(cancellations_count, 0) as cancellations_count,
|
||||
COALESCE(points_extra, '{}'::jsonb) as points_extra, created_at
|
||||
FROM clients ORDER BY created_at DESC`).Scan(&rows).Error
|
||||
if err != nil {
|
||||
@@ -102,16 +104,17 @@ func (d *Database) GetAllClients() ([]*models.Client, error) {
|
||||
clients := make([]*models.Client, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
client := &models.Client{
|
||||
ID: row.ID,
|
||||
Username: row.Username,
|
||||
Password: row.Password,
|
||||
Nom: row.Nom,
|
||||
Prenom: row.Prenom,
|
||||
Telephone: row.Telephone,
|
||||
Command: row.Command,
|
||||
Amende: row.Amende,
|
||||
ReferralBalance: row.ReferralBalance,
|
||||
CreatedAt: row.CreatedAt,
|
||||
ID: row.ID,
|
||||
Username: row.Username,
|
||||
Password: row.Password,
|
||||
Nom: row.Nom,
|
||||
Prenom: row.Prenom,
|
||||
Telephone: row.Telephone,
|
||||
Command: row.Command,
|
||||
Amende: row.Amende,
|
||||
ReferralBalance: row.ReferralBalance,
|
||||
CancellationsCount: row.CancellationsCount,
|
||||
CreatedAt: row.CreatedAt,
|
||||
}
|
||||
client.PointsExtra = map[string]int{}
|
||||
if len(row.PointsExtraJSON) > 0 {
|
||||
@@ -125,14 +128,15 @@ func (d *Database) GetAllClients() ([]*models.Client, error) {
|
||||
|
||||
// UpdateClient met à jour un client existant
|
||||
func (d *Database) UpdateClient(client *models.Client) error {
|
||||
result := d.GDB.Exec(`
|
||||
UPDATE clients
|
||||
SET username = ?, password = ?, nom = ?, prenom = ?, telephone = ?,
|
||||
command = ?, amende = ?
|
||||
WHERE id = ?`,
|
||||
client.Username, client.Password, client.Nom, client.Prenom, client.Telephone,
|
||||
client.Command, client.Amende, client.ID,
|
||||
)
|
||||
result := d.GDB.Model(&models.Client{}).Where("id = ?", client.ID).Updates(map[string]any{
|
||||
"username": client.Username,
|
||||
"password": client.Password,
|
||||
"nom": client.Nom,
|
||||
"prenom": client.Prenom,
|
||||
"telephone": client.Telephone,
|
||||
"command": client.Command,
|
||||
"amende": client.Amende,
|
||||
})
|
||||
if result.Error != nil {
|
||||
return fmt.Errorf("erreur lors de la mise à jour du client: %w", result.Error)
|
||||
}
|
||||
@@ -147,7 +151,7 @@ func (d *Database) UpdateClient(client *models.Client) error {
|
||||
func (d *Database) DeleteClient(id int) error {
|
||||
_ = d.RevokeAllUserTokens(id, "client")
|
||||
|
||||
result := d.GDB.Exec(`DELETE FROM clients WHERE id = ?`, id)
|
||||
result := d.GDB.Delete(&models.Client{}, id)
|
||||
if result.Error != nil {
|
||||
return fmt.Errorf("erreur lors de la suppression du client: %w", result.Error)
|
||||
}
|
||||
@@ -160,7 +164,7 @@ func (d *Database) DeleteClient(id int) error {
|
||||
|
||||
// UpdateClientPassword met à jour le mot de passe d'un client
|
||||
func (d *Database) UpdateClientPassword(clientID int, hashedPassword string) error {
|
||||
result := d.GDB.Exec(`UPDATE clients SET password = ? WHERE id = ?`, hashedPassword, clientID)
|
||||
result := d.GDB.Model(&models.Client{}).Where("id = ?", clientID).Update("password", hashedPassword)
|
||||
if result.Error != nil {
|
||||
return fmt.Errorf("erreur lors de la mise à jour du mot de passe: %w", result.Error)
|
||||
}
|
||||
@@ -173,9 +177,10 @@ func (d *Database) UpdateClientPassword(clientID int, hashedPassword string) err
|
||||
|
||||
// UpdateClientPasswordAndClearFlag met à jour le mot de passe et remet must_change_password à false
|
||||
func (d *Database) UpdateClientPasswordAndClearFlag(clientID int, hashedPassword string) error {
|
||||
result := d.GDB.Exec(`
|
||||
UPDATE clients SET password = ?, must_change_password = FALSE, updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ?`, hashedPassword, clientID)
|
||||
result := d.GDB.Model(&models.Client{}).Where("id = ?", clientID).Updates(map[string]any{
|
||||
"password": hashedPassword,
|
||||
"must_change_password": false,
|
||||
})
|
||||
if result.Error != nil {
|
||||
return fmt.Errorf("erreur lors de la mise à jour du mot de passe: %w", result.Error)
|
||||
}
|
||||
@@ -254,9 +259,7 @@ func (d *Database) PayClientPenalties(username string, amountPaid float64) error
|
||||
return fmt.Errorf("montant insuffisant: %.2f payé, %.2f requis", amountPaid, currentAmount)
|
||||
}
|
||||
|
||||
result := d.GDB.Exec(`
|
||||
UPDATE clients SET amende = 0, updated_at = CURRENT_TIMESTAMP
|
||||
WHERE username = ?`, username)
|
||||
result := d.GDB.Model(&models.Client{}).Where("username = ?", username).Update("amende", 0.0)
|
||||
if result.Error != nil {
|
||||
log.Printf("❌ [PayClientPenalties] Erreur UPDATE: %v", result.Error)
|
||||
return fmt.Errorf("erreur paiement pénalités: %w", result.Error)
|
||||
@@ -273,7 +276,7 @@ func (d *Database) PayClientPenalties(username string, amountPaid float64) error
|
||||
|
||||
// IncrementClientCommandCount incrémente le compteur de commandes du client
|
||||
func (d *Database) IncrementClientCommandCount(username string) error {
|
||||
result := d.GDB.Exec(`UPDATE clients SET command = command + 1 WHERE username = ?`, username)
|
||||
result := d.GDB.Model(&models.Client{}).Where("username = ?", username).UpdateColumn("command", gorm.Expr("command + 1"))
|
||||
if result.Error != nil {
|
||||
return fmt.Errorf("erreur lors de l'incrémentation du compteur: %w", result.Error)
|
||||
}
|
||||
|
||||
@@ -212,6 +212,7 @@ func (d *Database) GetCommandItems(commandID int) ([]map[string]interface{}, err
|
||||
LivreurAssign *string `gorm:"column:livreur_assign"`
|
||||
CommandCreatedAt *time.Time `gorm:"column:command_created_at"`
|
||||
Category string `gorm:"column:category"`
|
||||
ClientOrderNumber int `gorm:"column:client_order_number"`
|
||||
}
|
||||
|
||||
err := d.GDB.Raw(`
|
||||
@@ -236,7 +237,8 @@ func (d *Database) GetCommandItems(commandID int) ([]map[string]interface{}, err
|
||||
c.referral_used,
|
||||
c.livreur_assign,
|
||||
c.created_at as command_created_at,
|
||||
p.category
|
||||
p.category,
|
||||
c.client_order_id as client_order_number
|
||||
FROM command_items ci
|
||||
LEFT JOIN commandes c ON ci.command_id = c.id
|
||||
LEFT JOIN products p ON ci.product_id = p.id
|
||||
@@ -280,8 +282,9 @@ func (d *Database) GetCommandItems(commandID int) ([]map[string]interface{}, err
|
||||
"total_prix": row.TotalPrix,
|
||||
"referral_used": row.ReferralUsed,
|
||||
"livreur_assign": ptrStr(row.LivreurAssign),
|
||||
"command_created_at": commandCreatedAt,
|
||||
"category": row.Category,
|
||||
"command_created_at": commandCreatedAt,
|
||||
"category": row.Category,
|
||||
"client_order_number": row.ClientOrderNumber,
|
||||
}
|
||||
items = append(items, item)
|
||||
}
|
||||
|
||||
+110
-106
@@ -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
|
||||
}
|
||||
|
||||
@@ -187,6 +187,25 @@ func InitDB() *Database {
|
||||
log.Fatalf("❌ Erreur backfill commandes.client_order_id: %v", err)
|
||||
}
|
||||
|
||||
// Migration: raison d'annulation par le client
|
||||
if _, err = database.Exec(`ALTER TABLE commandes ADD COLUMN IF NOT EXISTS cancel_reason TEXT`); err != nil {
|
||||
log.Fatalf("❌ Erreur migration commandes.cancel_reason: %v", err)
|
||||
}
|
||||
|
||||
// Migration: coordonnées GPS de destination et du livreur
|
||||
if _, err = database.Exec(`ALTER TABLE commandes ADD COLUMN IF NOT EXISTS dest_latitude DOUBLE PRECISION`); err != nil {
|
||||
log.Fatalf("❌ Erreur migration commandes.dest_latitude: %v", err)
|
||||
}
|
||||
if _, err = database.Exec(`ALTER TABLE commandes ADD COLUMN IF NOT EXISTS dest_longitude DOUBLE PRECISION`); err != nil {
|
||||
log.Fatalf("❌ Erreur migration commandes.dest_longitude: %v", err)
|
||||
}
|
||||
if _, err = database.Exec(`ALTER TABLE commandes ADD COLUMN IF NOT EXISTS livreur_latitude DOUBLE PRECISION`); err != nil {
|
||||
log.Fatalf("❌ Erreur migration commandes.livreur_latitude: %v", err)
|
||||
}
|
||||
if _, err = database.Exec(`ALTER TABLE commandes ADD COLUMN IF NOT EXISTS livreur_longitude DOUBLE PRECISION`); err != nil {
|
||||
log.Fatalf("❌ Erreur migration commandes.livreur_longitude: %v", err)
|
||||
}
|
||||
|
||||
// Migration: table de suivi des paiements crypto
|
||||
if _, err = database.Exec(`
|
||||
CREATE TABLE IF NOT EXISTS crypto_payments (
|
||||
@@ -264,7 +283,6 @@ func (db *Database) createTables() error {
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);`,
|
||||
`ALTER TABLE clients ADD COLUMN IF NOT EXISTS referral_balance NUMERIC(10,2) DEFAULT 0.0;`,
|
||||
|
||||
// ============================
|
||||
// TABLE jwt_tokens
|
||||
@@ -423,7 +441,7 @@ func (db *Database) createTables() error {
|
||||
`CREATE INDEX IF NOT EXISTS idx_command_items_client_username ON command_items(client_username);`,
|
||||
`CREATE INDEX IF NOT EXISTS idx_command_items_status ON command_items(status);`,
|
||||
`CREATE INDEX IF NOT EXISTS idx_command_items_produit ON command_items(produit);`,
|
||||
`CREATE INDEX IF NOT EXISTS idx_jwt_user_id ON jwt_tokens(user_id);`,
|
||||
`CREATE INDEX IF NOT EXISTS idx_jwt_user_id ON jwt_tokens(user_id);`,
|
||||
`CREATE INDEX IF NOT EXISTS idx_jwt_user_type ON jwt_tokens(user_type);`,
|
||||
`CREATE INDEX IF NOT EXISTS idx_jwt_token ON jwt_tokens(token);`,
|
||||
`CREATE INDEX IF NOT EXISTS idx_jwt_date_fin ON jwt_tokens(date_fin);`,
|
||||
|
||||
@@ -3,6 +3,7 @@ package db
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"gestion/models"
|
||||
"gestion/services"
|
||||
"log"
|
||||
"time"
|
||||
@@ -64,7 +65,7 @@ func (d *Database) NotifyAllAdminCabine(commandID int, clientUsername, deliveryA
|
||||
var users []struct {
|
||||
Username string `gorm:"column:username"`
|
||||
}
|
||||
if err := d.GDB.Raw(`SELECT username FROM users WHERE role IN ('admin','cabine')`).Scan(&users).Error; err != nil {
|
||||
if err := d.GDB.Model(&models.User{}).Select("username").Where("role IN ?", []string{"admin", "cabine"}).Scan(&users).Error; err != nil {
|
||||
log.Printf("❌ [ADMIN_NOTIF] Erreur lecture users admin/cabine: %v", err)
|
||||
return
|
||||
}
|
||||
@@ -103,7 +104,7 @@ func (d *Database) NotifyAllAdminCabineAlert(alertID int, livreurUsername, alert
|
||||
var users []struct {
|
||||
Username string `gorm:"column:username"`
|
||||
}
|
||||
if err := d.GDB.Raw(`SELECT username FROM users WHERE role IN ('admin','cabine')`).Scan(&users).Error; err != nil {
|
||||
if err := d.GDB.Model(&models.User{}).Select("username").Where("role IN ?", []string{"admin", "cabine"}).Scan(&users).Error; err != nil {
|
||||
log.Printf("❌ [ALERT_NOTIF] Erreur lecture users admin/cabine: %v", err)
|
||||
return
|
||||
}
|
||||
@@ -136,18 +137,3 @@ func (d *Database) NotifyAllAdminCabineAlert(alertID int, livreurUsername, alert
|
||||
}
|
||||
log.Printf("🚨 [ALERT_NOTIF] Notif Redis (%d users) pour alerte #%d de %s", count, alertID, livreurUsername)
|
||||
}
|
||||
|
||||
// AddDeliveryRating ajoute une note pour un livreur
|
||||
func (d *Database) AddDeliveryRating(livreurUsername string, commandID, rating int, comment string) error {
|
||||
err := d.GDB.Exec(`
|
||||
INSERT INTO delivery_ratings (livreur_username, command_id, rating, comment, created_at)
|
||||
VALUES (?, ?, ?, ?, NOW())`,
|
||||
livreurUsername, commandID, rating, comment).Error
|
||||
if err != nil {
|
||||
log.Printf("⚠️ Erreur sauvegarde note livreur: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("⭐ Note %d/5 ajoutée pour livreur %s (commande %d)", rating, livreurUsername, commandID)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package db
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gestion/models"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@@ -19,7 +20,9 @@ func (d *Database) CreditClientReferral(username string, amount float64) error {
|
||||
if amount <= 0 {
|
||||
return fmt.Errorf("le montant doit être positif")
|
||||
}
|
||||
result := d.GDB.Exec(`UPDATE clients SET referral_balance = referral_balance + ? WHERE username = ?`, amount, username)
|
||||
result := d.GDB.Model(&models.Client{}).Where("username = ?", username).Updates(map[string]any{
|
||||
"referral_balance": gorm.Expr("referral_balance + ?", amount),
|
||||
})
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
"gestion/models"
|
||||
"log"
|
||||
"sort"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// GetClientCancellationsCount récupère le nombre d'annulations tardives d'un client
|
||||
@@ -17,7 +19,7 @@ func (d *Database) GetClientCancellationsCount(username string) (int, error) {
|
||||
var result struct {
|
||||
Count int `gorm:"column:count"`
|
||||
}
|
||||
err := d.GDB.Raw(`SELECT COALESCE(cancellations_count, 0) as count FROM clients WHERE username = ?`, username).Scan(&result).Error
|
||||
err := d.GDB.Table("clients").Select("COALESCE(cancellations_count, 0) as count").Where("username = ?", username).Scan(&result).Error
|
||||
if err != nil {
|
||||
log.Printf("❌ [GetCancellationsCount] Erreur: %v", err)
|
||||
return 0, fmt.Errorf("erreur récupération compteur: %w", err)
|
||||
@@ -27,11 +29,9 @@ func (d *Database) GetClientCancellationsCount(username string) (int, error) {
|
||||
|
||||
// IncrementClientCancellationsCount incrémente le compteur d'annulations
|
||||
func (d *Database) IncrementClientCancellationsCount(username string) error {
|
||||
result := d.GDB.Exec(`
|
||||
UPDATE clients
|
||||
SET cancellations_count = COALESCE(cancellations_count, 0) + 1,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE username = ?`, username)
|
||||
result := d.GDB.Model(&models.Client{}).Where("username = ?", username).Updates(map[string]any{
|
||||
"cancellations_count": gorm.Expr("COALESCE(cancellations_count, 0) + 1"),
|
||||
})
|
||||
if result.Error != nil {
|
||||
log.Printf("❌ [IncrementCancellations] Erreur: %v", result.Error)
|
||||
return fmt.Errorf("erreur incrémentation: %w", result.Error)
|
||||
@@ -98,11 +98,7 @@ func (d *Database) ApplyCancellationPenalty(username string) (int, error) {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
result := d.GDB.Exec(`
|
||||
UPDATE clients
|
||||
SET amende = ?,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE username = ?`, float64(penalty), username)
|
||||
result := d.GDB.Model(&models.Client{}).Where("username = ?", username).Update("amende", float64(penalty))
|
||||
if result.Error != nil {
|
||||
log.Printf("❌ [ApplyCancellationPenalty] Erreur UPDATE: %v", result.Error)
|
||||
return 0, fmt.Errorf("erreur application pénalité: %w", result.Error)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"gestion/models"
|
||||
"strconv"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@@ -40,6 +41,7 @@ func DefaultSettings() models.AppSettings {
|
||||
},
|
||||
PointsEnabled: true,
|
||||
ReferralEnabled: true,
|
||||
ReferralAmount: 0,
|
||||
PointsPools: []models.PointsPool{
|
||||
{
|
||||
Key: "pool_0",
|
||||
@@ -90,7 +92,7 @@ func (d *Database) GetSettings() (models.AppSettings, error) {
|
||||
Key string `gorm:"column:key"`
|
||||
Value string `gorm:"column:value"`
|
||||
}
|
||||
if err := d.GDB.Raw(`SELECT key, value FROM app_settings`).Scan(&rows).Error; err != nil {
|
||||
if err := d.GDB.Table("app_settings").Select("key, value").Scan(&rows).Error; err != nil {
|
||||
return settings, fmt.Errorf("erreur lecture settings: %w", err)
|
||||
}
|
||||
|
||||
@@ -109,6 +111,10 @@ func (d *Database) GetSettings() (models.AppSettings, error) {
|
||||
}
|
||||
case "referral_enabled":
|
||||
settings.ReferralEnabled = row.Value == "true"
|
||||
case "referral_amount":
|
||||
if v, err := strconv.ParseFloat(row.Value, 64); err == nil {
|
||||
settings.ReferralAmount = v
|
||||
}
|
||||
case "crypto_payment_enabled":
|
||||
settings.CryptoPaymentEnabled = row.Value == "true"
|
||||
case "crypto_only":
|
||||
@@ -207,6 +213,7 @@ func (d *Database) UpdateSettings(s models.AppSettings) error {
|
||||
{"points_enabled", boolStr(s.PointsEnabled)},
|
||||
{"points_pools", string(poolsJSON)},
|
||||
{"referral_enabled", boolStr(s.ReferralEnabled)},
|
||||
{"referral_amount", strconv.FormatFloat(s.ReferralAmount, 'f', 2, 64)},
|
||||
{"crypto_payment_enabled", boolStr(s.CryptoPaymentEnabled)},
|
||||
{"crypto_only", boolStr(s.CryptoOnly)},
|
||||
{"nowpayments_api_key", s.NowPaymentsAPIKey},
|
||||
|
||||
@@ -67,15 +67,14 @@ func ValidateAndConsumeLinkToken(token string) (username, role string, err error
|
||||
}
|
||||
|
||||
func (d *Database) SaveClientTelegramChatID(username string, chatID int64) error {
|
||||
return d.GDB.Exec(`UPDATE clients SET telegram_chat_id = ? WHERE username = ?`, chatID, username).Error
|
||||
return d.GDB.Model(&models.Client{}).Where("username = ?", username).Update("telegram_chat_id", chatID).Error
|
||||
}
|
||||
|
||||
func (d *Database) GetClientTelegramChatID(username string) (int64, bool, error) {
|
||||
var result struct {
|
||||
ChatID *int64 `gorm:"column:telegram_chat_id"`
|
||||
}
|
||||
err := d.GDB.Raw(`SELECT telegram_chat_id FROM clients WHERE username = ?`, username).Scan(&result).Error
|
||||
if err != nil {
|
||||
if err := d.GDB.Table("clients").Select("telegram_chat_id").Where("username = ?", username).Limit(1).Scan(&result).Error; err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
if result.ChatID == nil {
|
||||
@@ -85,19 +84,18 @@ func (d *Database) GetClientTelegramChatID(username string) (int64, bool, error)
|
||||
}
|
||||
|
||||
func (d *Database) DeleteClientTelegramChatID(username string) error {
|
||||
return d.GDB.Exec(`UPDATE clients SET telegram_chat_id = NULL WHERE username = ?`, username).Error
|
||||
return d.GDB.Model(&models.Client{}).Where("username = ?", username).Update("telegram_chat_id", nil).Error
|
||||
}
|
||||
|
||||
func (d *Database) SaveUserTelegramChatID(username string, chatID int64) error {
|
||||
return d.GDB.Exec(`UPDATE users SET telegram_chat_id = ? WHERE username = ?`, chatID, username).Error
|
||||
return d.GDB.Model(&models.User{}).Where("username = ?", username).Update("telegram_chat_id", chatID).Error
|
||||
}
|
||||
|
||||
func (d *Database) GetUserTelegramChatID(username string) (int64, bool, error) {
|
||||
var result struct {
|
||||
ChatID *int64 `gorm:"column:telegram_chat_id"`
|
||||
}
|
||||
err := d.GDB.Raw(`SELECT telegram_chat_id FROM users WHERE username = ?`, username).Scan(&result).Error
|
||||
if err != nil {
|
||||
if err := d.GDB.Table("users").Select("telegram_chat_id").Where("username = ?", username).Limit(1).Scan(&result).Error; err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
if result.ChatID == nil {
|
||||
@@ -107,7 +105,7 @@ func (d *Database) GetUserTelegramChatID(username string) (int64, bool, error) {
|
||||
}
|
||||
|
||||
func (d *Database) DeleteUserTelegramChatID(username string) error {
|
||||
return d.GDB.Exec(`UPDATE users SET telegram_chat_id = NULL WHERE username = ?`, username).Error
|
||||
return d.GDB.Model(&models.User{}).Where("username = ?", username).Update("telegram_chat_id", nil).Error
|
||||
}
|
||||
|
||||
// GetUserByTelegramChatID retrouve un utilisateur (clients + users) par chat_id
|
||||
@@ -115,7 +113,7 @@ func (d *Database) GetUserByTelegramChatID(chatID int64) (username, role string,
|
||||
var clientResult struct {
|
||||
Username string `gorm:"column:username"`
|
||||
}
|
||||
if err = d.GDB.Raw(`SELECT username FROM clients WHERE telegram_chat_id = ?`, chatID).Scan(&clientResult).Error; err == nil && clientResult.Username != "" {
|
||||
if err = d.GDB.Table("clients").Select("username").Where("telegram_chat_id = ?", chatID).Limit(1).Scan(&clientResult).Error; err == nil && clientResult.Username != "" {
|
||||
return clientResult.Username, "client", nil
|
||||
}
|
||||
|
||||
@@ -123,7 +121,7 @@ func (d *Database) GetUserByTelegramChatID(chatID int64) (username, role string,
|
||||
Username string `gorm:"column:username"`
|
||||
Role string `gorm:"column:role"`
|
||||
}
|
||||
if err = d.GDB.Raw(`SELECT username, role FROM users WHERE telegram_chat_id = ?`, chatID).Scan(&userResult).Error; err == nil && userResult.Username != "" {
|
||||
if err = d.GDB.Model(&models.User{}).Select("username, role").Where("telegram_chat_id = ?", chatID).Limit(1).Scan(&userResult).Error; err == nil && userResult.Username != "" {
|
||||
return userResult.Username, userResult.Role, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ func (d *Database) ProcessScheduledNotifications() error {
|
||||
|
||||
// SendETANotification envoie une notification ETA
|
||||
func (d *Database) SendETANotification(commandID int, notifType string) {
|
||||
message := fmt.Sprintf("Votre commande #%d arrive dans %s", commandID, notifType)
|
||||
message := fmt.Sprintf("Votre commande #%d arrive dans %s", d.GetClientOrderID(commandID), notifType)
|
||||
|
||||
channel := fmt.Sprintf("notifications:command:%d", commandID)
|
||||
Redis.Publish(RedisCtx, channel, message)
|
||||
|
||||
@@ -2,7 +2,7 @@ package db
|
||||
|
||||
import "fmt"
|
||||
|
||||
func extractCommandID(member interface{}) int {
|
||||
func extractCommandID(member any) int {
|
||||
switch v := member.(type) {
|
||||
case int:
|
||||
return v
|
||||
|
||||
@@ -70,7 +70,6 @@ func (d *Database) AssignCommandToDeliverymanQueue(commandID int, deliveryman st
|
||||
|
||||
d.UpdateCommandStatus(commandID, "assigned")
|
||||
d.AssignDeliveryPerson(commandID, deliveryman)
|
||||
// ✅ MODIFIÉ: Position dans la queue pour info seulement
|
||||
d.SetCommandETAWithDetails(commandID, totalETA, int(currentQueueSize)+1)
|
||||
|
||||
limitInfo := ""
|
||||
@@ -93,10 +92,8 @@ func (d *Database) AssignCommandToDeliverymanQueueUnlimited(deliveryman string,
|
||||
queueKey := fmt.Sprintf("queue:deliveryman:%s", deliveryman)
|
||||
currentQueueSize, _ := Redis.ZCard(RedisCtx, queueKey).Result()
|
||||
|
||||
// ✅ MODIFIÉ: Calculer le temps de trajet direct depuis la position du livreur
|
||||
travelTime := d.CalculateETAForDeliveryman(deliveryman, queueItem.Lat, queueItem.Lng)
|
||||
|
||||
// ✅ ETA = temps de trajet direct uniquement
|
||||
queueItem.EstimatedETA = travelTime
|
||||
|
||||
err := d.AddToDeliverymanQueue(deliveryman, queueItem)
|
||||
|
||||
@@ -216,17 +216,17 @@ func (d *Database) StartQueueCleanupScheduler() {
|
||||
// ============================================
|
||||
|
||||
// GetQueueValidationReport génère un rapport de validation sans supprimer
|
||||
func (d *Database) GetQueueValidationReport() (map[string]interface{}, error) {
|
||||
func (d *Database) GetQueueValidationReport() (map[string]any, error) {
|
||||
keys, err := Redis.Keys(RedisCtx, "queue:pending:*").Result()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
report := map[string]interface{}{
|
||||
report := map[string]any{
|
||||
"total_commands": len(keys),
|
||||
"valid_commands": 0,
|
||||
"invalid_commands": 0,
|
||||
"invalid_details": []map[string]interface{}{},
|
||||
"invalid_details": []map[string]any{},
|
||||
"validation_results": []string{},
|
||||
}
|
||||
|
||||
@@ -259,7 +259,7 @@ func (d *Database) GetQueueValidationReport() (map[string]interface{}, error) {
|
||||
|
||||
if len(issues) > 0 {
|
||||
report["invalid_commands"] = report["invalid_commands"].(int) + 1
|
||||
report["invalid_details"] = append(report["invalid_details"].([]map[string]interface{}), map[string]interface{}{
|
||||
report["invalid_details"] = append(report["invalid_details"].([]map[string]any), map[string]any{
|
||||
"command_id": queueItem.CommandID,
|
||||
"issues": issues,
|
||||
"data": queueItem,
|
||||
|
||||
@@ -11,10 +11,6 @@ import (
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
// ============================================
|
||||
// 🆕 GESTION AUTOMATIQUE DU STATUT BUSY
|
||||
// ============================================
|
||||
|
||||
// UpdateDeliverymanStatusBasedOnQueue met à jour automatiquement le statut
|
||||
func (d *Database) UpdateDeliverymanStatusBasedOnQueue(deliveryman string) error {
|
||||
queueKey := fmt.Sprintf("queue:deliveryman:%s", deliveryman)
|
||||
|
||||
Reference in New Issue
Block a user