211 lines
13 KiB
Go
211 lines
13 KiB
Go
package models
|
|
|
|
type PostalZone struct {
|
|
Name string `json:"name"`
|
|
MinAmount float64 `json:"min_amount"`
|
|
Codes []string `json:"codes"`
|
|
}
|
|
|
|
// PointsTier représente un palier du barème de points
|
|
// Si Max == 0, il n'y a pas de borne supérieure (illimité)
|
|
type PointsTier struct {
|
|
Min float64 `json:"min"`
|
|
Max float64 `json:"max"` // 0 = illimité
|
|
Points int `json:"points"`
|
|
}
|
|
|
|
// RewardProductQuantity associe un produit à sa propre quantité offerte / à
|
|
// -50%, pour le cas où une catégorie n'est pas configurée en "tous les
|
|
// produits" — ex: produit A à 2g offerts, produit B à 1g offert, tous deux
|
|
// dans la même catégorie et le même type de récompense.
|
|
type RewardProductQuantity struct {
|
|
ProductID int `json:"product_id"`
|
|
Quantity float64 `json:"quantity"`
|
|
}
|
|
|
|
// RewardCategoryConfig définit les produits éligibles dans une catégorie pour une récompense,
|
|
// le type de récompense appliqué pour cette catégorie précise, et la quantité
|
|
// concernée (ex: 1g offert, ou 2g à -50%) — la quantité correspond au palier
|
|
// de prix catalogue du produit (voir GetActiveProductPrice), pas une valeur
|
|
// libre : ex. "30€ offert = 1g" si le produit a un palier quantity=1 à 30€.
|
|
//
|
|
// Si AllProducts = true, Quantity s'applique uniformément à tous les produits
|
|
// de la catégorie. Si AllProducts = false, chaque produit sélectionné dans
|
|
// Products a sa propre quantité (Quantity au niveau catégorie est alors ignoré).
|
|
type RewardCategoryConfig struct {
|
|
Category string `json:"category"` // nom de la catégorie
|
|
Type string `json:"type"` // "free_product" (défaut) | "half_price_product"
|
|
AllProducts bool `json:"all_products"` // true = tous les produits de la catégorie
|
|
Quantity float64 `json:"quantity"` // quantité uniforme si AllProducts = true
|
|
Products []RewardProductQuantity `json:"products"` // produits + quantité individuelle si AllProducts = false
|
|
}
|
|
|
|
// RewardItem représente un produit résolu à ajouter au panier lors d'un
|
|
// claim (ProductID + Quantity + Price effectif) — construit dynamiquement à
|
|
// partir des CategoryConfigs au moment du claim, plus une liste saisie à part.
|
|
type RewardItem struct {
|
|
ProductID int `json:"product_id"` // ID du produit ajouté au panier
|
|
Quantity float64 `json:"quantity"` // quantité offerte
|
|
Price float64 `json:"price"` // prix effectif facturé (0 si offert, 50% du prix catalogue si -50%)
|
|
}
|
|
|
|
// PointsReward représente la récompense débloquée à partir d'un seuil de points cumulés.
|
|
// Le type de récompense (gratuit ou -50%) et la quantité concernée sont
|
|
// définis par catégorie dans CategoryConfigs (voir RewardCategoryConfig) —
|
|
// les produits éligibles et leur quantité ne sont plus saisis à part.
|
|
type PointsReward struct {
|
|
Threshold int `json:"threshold"` // points cumulés nécessaires (ex: 20)
|
|
Description string `json:"description"` // description libre affichée au client
|
|
CategoryConfigs []RewardCategoryConfig `json:"category_configs"` // catégories + produits éligibles + type + quantité par catégorie
|
|
}
|
|
|
|
// PromotionProductQuantity associe un produit à sa propre quantité en promo,
|
|
// pour le cas où une catégorie n'est pas configurée en "tous les produits" —
|
|
// même logique que RewardProductQuantity mais pour les promotions.
|
|
type PromotionProductQuantity struct {
|
|
ProductID int `json:"product_id"`
|
|
Quantity float64 `json:"quantity"`
|
|
}
|
|
|
|
// CategoryPromotionConfig définit une promotion (réduction en %) appliquée
|
|
// automatiquement au prix catalogue d'un produit pour une quantité donnée —
|
|
// contrairement à RewardCategoryConfig, ça ne dépend d'aucun seuil de points :
|
|
// le prix réduit s'applique à tout client qui commande ce produit à cette
|
|
// quantité, affiché directement sur le produit. La quantité correspond au
|
|
// palier de prix catalogue existant (voir GetActiveProductPrice), pas une
|
|
// valeur libre.
|
|
//
|
|
// Si AllProducts = true, Quantity s'applique uniformément à tous les produits
|
|
// de la catégorie. Si AllProducts = false, chaque produit sélectionné dans
|
|
// Products a sa propre quantité (Quantity au niveau catégorie est alors ignoré).
|
|
type CategoryPromotionConfig struct {
|
|
Category string `json:"category"` // nom de la catégorie
|
|
DiscountPercent float64 `json:"discount_percent"` // pourcentage de réduction libre (ex: 10, 20, 33.5)
|
|
AllProducts bool `json:"all_products"` // true = tous les produits de la catégorie
|
|
Quantity float64 `json:"quantity"` // quantité uniforme si AllProducts = true
|
|
Products []PromotionProductQuantity `json:"products"` // produits + quantité individuelle si AllProducts = false
|
|
}
|
|
|
|
// FreeGiftTier définit un seuil d'achat et la quantité offerte associée, du
|
|
// même produit — plusieurs seuils peuvent coexister pour un même produit
|
|
// (ex: 10g achetés → 1g offert, 20g achetés → 3g offerts) ; le seuil le plus
|
|
// élevé atteint par la quantité commandée est retenu (voir ResolveFreeGift).
|
|
type FreeGiftTier struct {
|
|
BuyQuantity float64 `json:"buy_quantity"` // quantité à acheter pour déclencher l'offre
|
|
FreeQuantity float64 `json:"free_quantity"` // quantité offerte du même produit
|
|
}
|
|
|
|
// FreeGiftProductQuantity associe un produit à ses propres seuils
|
|
// d'achat/offre, pour le cas où une catégorie n'est pas configurée en "tous
|
|
// les produits" — même logique que PromotionProductQuantity mais pour les
|
|
// offres quantité achetée/offerte.
|
|
type FreeGiftProductQuantity struct {
|
|
ProductID int `json:"product_id"`
|
|
Tiers []FreeGiftTier `json:"tiers"`
|
|
}
|
|
|
|
// CategoryFreeGiftConfig définit une offre "achetez X, Y offert" (du même
|
|
// produit) appliquée automatiquement dès que la quantité ajoutée au panier
|
|
// atteint un seuil configuré — indépendant des points de fidélité et des
|
|
// promotions (cumulable avec elles).
|
|
//
|
|
// Si AllProducts = true, Tiers s'applique uniformément à tous les produits de
|
|
// la catégorie. Si AllProducts = false, chaque produit sélectionné dans
|
|
// Products a ses propres seuils (Tiers au niveau catégorie est alors ignoré).
|
|
type CategoryFreeGiftConfig struct {
|
|
Category string `json:"category"` // nom de la catégorie
|
|
AllProducts bool `json:"all_products"` // true = tous les produits de la catégorie
|
|
Tiers []FreeGiftTier `json:"tiers"` // seuils uniformes si AllProducts = true
|
|
Products []FreeGiftProductQuantity `json:"products"` // produits + seuils individuels si AllProducts = false
|
|
}
|
|
|
|
// DaySchedule représente les horaires de livraison pour un jour de la semaine
|
|
type DaySchedule struct {
|
|
Enabled bool `json:"enabled"`
|
|
OpenTime string `json:"open_time"` // ex: "09:00"
|
|
CloseTime string `json:"close_time"` // ex: "20:00"
|
|
}
|
|
|
|
// DeliverySchedule représente les horaires de livraison pour chaque jour
|
|
type DeliverySchedule struct {
|
|
Monday DaySchedule `json:"monday"`
|
|
Tuesday DaySchedule `json:"tuesday"`
|
|
Wednesday DaySchedule `json:"wednesday"`
|
|
Thursday DaySchedule `json:"thursday"`
|
|
Friday DaySchedule `json:"friday"`
|
|
Saturday DaySchedule `json:"saturday"`
|
|
Sunday DaySchedule `json:"sunday"`
|
|
}
|
|
|
|
type PointsPool struct {
|
|
Key string `json:"key"` // identifiant interne (ex: "pool_0")
|
|
Name string `json:"name"` // nom affiché (ex: "Cannabis", "Accessoires")
|
|
Categories []string `json:"categories"` // catégories de produits assignées à ce pool
|
|
Tiers []PointsTier `json:"tiers"` // barème de points
|
|
}
|
|
|
|
// PenaltyTier représente un palier d'amende : à partir de MinCancel annulations, Amount est appliqué
|
|
type PenaltyTier struct {
|
|
MinCancel int `json:"min_cancel"` // nombre d'annulations à partir duquel ce palier s'applique
|
|
Amount int `json:"amount"` // montant de l'amende
|
|
}
|
|
|
|
// CategoryRoute associe un livreur à une ou plusieurs catégories de produits
|
|
type CategoryRoute struct {
|
|
DeliverymanUsername string `json:"deliveryman_username"`
|
|
Categories []string `json:"categories"`
|
|
}
|
|
|
|
// DeliveryModeConfig configure le mode d'assignation des livreurs
|
|
// Mode "single" → un seul livreur, toutes catégories confondues
|
|
// Mode "category_based" → chaque livreur gère ses catégories dédiées
|
|
type DeliveryModeConfig struct {
|
|
Mode string `json:"mode"` // "single" | "category_based"
|
|
CategoryRoutes []CategoryRoute `json:"category_routes"` // utilisé uniquement en mode category_based
|
|
}
|
|
|
|
// AppSettings contient les paramètres globaux de l'application
|
|
type AppSettings struct {
|
|
PenaltiesEnabled bool `json:"penalties_enabled"`
|
|
ShowAmendeScore bool `json:"show_amende_score"` // afficher le score d'amendes aux clients/cabine
|
|
PenaltyTiers []PenaltyTier `json:"penalty_tiers"` // barème des amendes (liste configurable)
|
|
PointsEnabled bool `json:"points_enabled"` // afficher/activer le système de points
|
|
PointsPools []PointsPool `json:"points_pools"` // types de points personnalisés
|
|
PointsReward *PointsReward `json:"points_reward"` // récompense globale par palier de points
|
|
PromotionsEnabled bool `json:"promotions_enabled"` // activer/désactiver les promotions
|
|
Promotions []CategoryPromotionConfig `json:"promotions"` // promotions (% de réduction) par catégorie
|
|
FreeGiftsEnabled bool `json:"free_gifts_enabled"` // activer/désactiver les offres "achetez X, Y offert"
|
|
FreeGifts []CategoryFreeGiftConfig `json:"free_gifts"` // offres quantité achetée/offerte par catégorie
|
|
ReferralEnabled bool `json:"referral_enabled"` // activer/désactiver le système de parrainage
|
|
ReferralAmount float64 `json:"referral_amount"` // montant crédité par parrainage
|
|
CryptoPaymentEnabled bool `json:"crypto_payment_enabled"` // activer/désactiver le paiement crypto
|
|
CryptoOnly bool `json:"crypto_only"` // forcer le paiement crypto uniquement (pas d'espèces)
|
|
NowPaymentsAPIKey string `json:"nowpayments_api_key"` // clé API NowPayments
|
|
NowPaymentsIPNSecret string `json:"nowpayments_ipn_secret"` // secret IPN NowPayments
|
|
NowPaymentsCurrencies []string `json:"nowpayments_currencies"` // cryptos acceptées (ex: ["btc","eth","ltc"])
|
|
DeliverySchedule DeliverySchedule `json:"delivery_schedule"` // horaires de livraison par jour
|
|
PostalZones []PostalZone `json:"postal_zones"` // zones de livraison avec minimum de commande
|
|
TelegramBotToken string `json:"telegram_bot_token"` // token du bot Telegram (BotFather) — pour le webhook de liaison
|
|
TelegramBotUsername string `json:"telegram_bot_username"` // username du bot (sans @)
|
|
TelegramNotificationsEnabled bool `json:"telegram_notifications_enabled"` // activer/désactiver les notifications Telegram
|
|
DeliveryMode DeliveryModeConfig `json:"delivery_mode"` // mode d'assignation des livreurs
|
|
ShopName string `json:"shop_name"` // nom affiché dans la sidebar du site client
|
|
Telegram2FAEnabled bool `json:"telegram_2fa_enabled"` // activer/désactiver l'authentification à deux facteurs
|
|
ContactTelegram string `json:"contact_telegram"` // numéro de téléphone Telegram du contact
|
|
// Palette de couleurs — espace admin
|
|
AdminColorPrimary string `json:"admin_color_primary"`
|
|
AdminColorSecondary string `json:"admin_color_secondary"`
|
|
AdminColorSuccess string `json:"admin_color_success"`
|
|
AdminColorDanger string `json:"admin_color_danger"`
|
|
AdminColorWarning string `json:"admin_color_warning"`
|
|
// Palette de couleurs — app client + site web
|
|
ClientColorPrimary string `json:"client_color_primary"`
|
|
ClientColorSecondary string `json:"client_color_secondary"`
|
|
ClientColorSuccess string `json:"client_color_success"`
|
|
ClientColorDanger string `json:"client_color_danger"`
|
|
ClientColorWarning string `json:"client_color_warning"`
|
|
// Dégradé du titre boutique sur le site web client
|
|
ClientTitleGradientFrom string `json:"client_title_gradient_from"`
|
|
ClientTitleGradientTo string `json:"client_title_gradient_to"`
|
|
}
|