125 lines
3.0 KiB
Go
125 lines
3.0 KiB
Go
package handlers
|
|
|
|
import "regexp"
|
|
|
|
// ============================================================
|
|
// Zones de livraison — minimum de commande par code postal
|
|
// ============================================================
|
|
// Remplis les listes de codes postaux quand tu les as.
|
|
// Un code postal absent de toutes les zones → commande refusée.
|
|
// ============================================================
|
|
|
|
type deliveryZone struct {
|
|
Name string
|
|
MinAmount float64
|
|
codes map[string]struct{}
|
|
}
|
|
|
|
var deliveryZones = []deliveryZone{
|
|
{
|
|
Name: "Zone 30€",
|
|
MinAmount: 30.0,
|
|
codes: postalSet([]string{
|
|
"44000",
|
|
"44100",
|
|
"44200",
|
|
"44300",
|
|
}),
|
|
},
|
|
{
|
|
Name: "Zone 50€",
|
|
MinAmount: 50.0,
|
|
codes: postalSet([]string{
|
|
"44400", // Rezé
|
|
"44880", // Les Sorinières / Sautron
|
|
"44120", // Vertou
|
|
"44230", // Saint-Sébastien-sur-Loire
|
|
"44115", // Basse-Goulaine / Haute-Goulaine
|
|
"44980", // Sainte-Luce-sur-Loire
|
|
"44470", // Carquefou
|
|
"44240", // La Chapelle-sur-Erdre
|
|
"44700", // Orvault
|
|
"44800", // Saint-Herblain
|
|
"44340", // Bouguenais
|
|
"44620", // La Montagne
|
|
"44830", // Bouaye
|
|
}),
|
|
},
|
|
{
|
|
Name: "Zone 100€",
|
|
MinAmount: 100.0,
|
|
codes: postalSet([]string{
|
|
"44860", // Pont-Saint-Martin / Saint-Aignan-Grandlieu
|
|
"44220", // Couëron
|
|
"44118", // La Chevrolière
|
|
"44830", // Brains
|
|
"44710", // Saint-Léger-les-Vignes
|
|
"44690", // La Haie-Fouassière
|
|
"44470", // Mauves-sur-Loire
|
|
"44240", // Sucé-sur-Erdre
|
|
"44119", // Grandchamp-des-Fontaines
|
|
}),
|
|
},
|
|
}
|
|
|
|
var postalCodeRe = regexp.MustCompile(`\b(\d{5})\b`)
|
|
|
|
// postalSet convertit une slice de codes en set pour lookup O(1).
|
|
func postalSet(codes []string) map[string]struct{} {
|
|
m := make(map[string]struct{}, len(codes))
|
|
for _, c := range codes {
|
|
m[c] = struct{}{}
|
|
}
|
|
return m
|
|
}
|
|
|
|
// extractPostalCode extrait le premier code postal à 5 chiffres d'une adresse.
|
|
func extractPostalCode(address string) string {
|
|
m := postalCodeRe.FindStringSubmatch(address)
|
|
if len(m) < 2 {
|
|
return ""
|
|
}
|
|
return m[1]
|
|
}
|
|
|
|
// zoneCheckResult est le résultat de la vérification de zone.
|
|
type zoneCheckResult struct {
|
|
PostalCode string
|
|
ZoneName string
|
|
MinAmount float64
|
|
OK bool
|
|
}
|
|
|
|
// checkDeliveryZone vérifie si le total respecte le minimum de la zone de l'adresse.
|
|
// Code postal introuvable → OK = false (refus).
|
|
// Code postal hors de toutes les zones → OK = false (refus).
|
|
func checkDeliveryZone(deliveryAddress string, total float64) zoneCheckResult {
|
|
code := extractPostalCode(deliveryAddress)
|
|
if code == "" {
|
|
return zoneCheckResult{
|
|
PostalCode: "",
|
|
ZoneName: "inconnue",
|
|
MinAmount: 0,
|
|
OK: false,
|
|
}
|
|
}
|
|
|
|
for _, zone := range deliveryZones {
|
|
if _, found := zone.codes[code]; found {
|
|
return zoneCheckResult{
|
|
PostalCode: code,
|
|
ZoneName: zone.Name,
|
|
MinAmount: zone.MinAmount,
|
|
OK: total >= zone.MinAmount,
|
|
}
|
|
}
|
|
}
|
|
|
|
return zoneCheckResult{
|
|
PostalCode: code,
|
|
ZoneName: "hors zone",
|
|
MinAmount: 0,
|
|
OK: false,
|
|
}
|
|
}
|