feat: add CSV export for approved orders && add non-delivery reason modal for livreurs

This commit is contained in:
2026-05-03 13:23:20 +02:00
parent a273484659
commit 7dc2686f6c
8 changed files with 233 additions and 14 deletions
+43
View File
@@ -1,6 +1,8 @@
package handlers
import (
"bytes"
"encoding/csv"
"fmt"
"gestion/db"
"gestion/utils"
@@ -259,6 +261,47 @@ func RespondToAddressProposal(c *gin.Context) {
})
}
func ExportApprovedCommandsCSV(c *gin.Context) {
database := c.MustGet("database").(*db.Database)
commands, err := database.GetApprovedCommands()
if err != nil {
log.Printf("❌ [EXPORT_CSV] Erreur: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur export CSV"})
return
}
var buf bytes.Buffer
w := csv.NewWriter(&buf)
_ = w.Write([]string{
"ID", "Client Order ID", "User ID", "Username",
"Statut", "Total (€)", "Adresse", "Livreur",
"Créé le", "Mis à jour le",
})
for _, cmd := range commands {
_ = w.Write([]string{
strconv.Itoa(cmd.ID),
strconv.Itoa(cmd.ClientOrderID),
strconv.Itoa(cmd.UserID),
cmd.Username,
cmd.Status,
strconv.FormatFloat(cmd.Total, 'f', 2, 64),
cmd.DeliveryAddress,
cmd.LivreurAssign,
cmd.CreatedAt.Format("2006-01-02 15:04:05"),
cmd.UpdatedAt.Format("2006-01-02 15:04:05"),
})
}
w.Flush()
filename := fmt.Sprintf("commandes_approved_%s.csv", time.Now().Format("2006-01-02"))
c.Header("Content-Type", "text/csv; charset=utf-8")
c.Header("Content-Disposition", "attachment; filename="+filename)
c.String(http.StatusOK, buf.String())
}
func GetAllCommands(c *gin.Context) {
database := c.MustGet("database").(*db.Database)
+58
View File
@@ -414,3 +414,61 @@ func UpdateDeliveryStatus(c *gin.Context) {
c.JSON(http.StatusOK, response)
}
// POST /api/v1/livreur/deliveries/:id/issue
func ReportDeliveryIssue(c *gin.Context) {
username := c.GetString("username")
if c.GetString("role") != "livreur" {
c.JSON(http.StatusForbidden, gin.H{"error": "Accès refusé"})
return
}
commandID, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "ID invalide"})
return
}
var req struct {
IssueType string `json:"issue_type" binding:"required"`
Description string `json:"description"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "issue_type requis"})
return
}
validTypes := map[string]bool{
"client_absent": true,
"wrong_address": true,
"refused_delivery": true,
"no_access": true,
"other": true,
}
if !validTypes[req.IssueType] {
c.JSON(http.StatusBadRequest, gin.H{"error": "Type de problème invalide"})
return
}
database := c.MustGet("database").(*db.Database)
command, err := database.GetCommandByID(commandID)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Commande introuvable"})
return
}
if livreur, _ := command["livreur_assign"].(string); livreur != username {
c.JSON(http.StatusForbidden, gin.H{"error": "Commande non assignée à vous"})
return
}
issue, err := database.CreateDeliveryIssue(commandID, req.IssueType, req.Description, username)
if err != nil {
log.Printf("❌ [ISSUE] Erreur création: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur création problème"})
return
}
log.Printf("📋 [ISSUE] Créé par %s pour commande #%d: %s", username, commandID, req.IssueType)
c.JSON(http.StatusCreated, gin.H{"success": true, "issue": issue})
}