Le développement rapide des sports d'hiver a transformé la vente de matériel de ski en un secteur numérique compétitif. Les systèmes de vente traditionnels souffrent souvent d'un manque de transparence sur les stocks et d'une interface utilisateur rigide. L'adoption d'une architecture découplée (découplage front-end/back-end) permet de répondre aux exigences modernes de performance, de maintenance facilitée et d'évolutivité. Cette approche garantit une expérience d'achat fluide tout en optimisant la gestion logistique en arrière-plan.
Stack Technique et Architecture
La solution repose sur un écosystème robuste garantissant la cohérence des données et la réactivité de l'interface :
- Back-end : Spring Boot assure la logique métier et l'exposition des services via une API RESTful. Il utilise le principe de "convention plutôt que configuration" pour accélérer le déploiement.
- Front-end : Vue.js est utilisé pour construire une interface utilisateur réactive et modulaire, s'appuyant sur des composants réutilisables.
- Persistance des données : MyBatis sert de pont entre le code Java et la base de données MySQL, permettant un contrôle précis sur les requêtes SQL.
- Sécurité : Un mécanisme d'authentification basé sur les tokens assure la protection des données sensibles des utilisateurs.
Conception de la Base de Données
Le schéma relationnel est structuré pour supporter des trasnactions complexes tout en maintenant une haute intégrité des données.
Table des Utilisateurs (app_user)
| Champ | Type | Description |
|---|---|---|
| id_user | BIGINT | Clé primaire, identifiant unique |
| account_name | VARCHAR(50) | Nom d'utilisateur unique |
| secure_pwd | VARCHAR(100) | Mot de passe haché |
| contact_email | VARCHAR(100) | Adresse électronique |
| phone_number | VARCHAR(20) | Téléphone de contact |
| created_at | DATETIME | Date d'inscription |
Table des Produits (ski_inventory)
| Champ | Type | Description |
|---|---|---|
| id_product | BIGINT | Clé primaire |
| label_name | VARCHAR(100) | Désignation de l'équipement |
| category_tag | VARCHAR(50) | Catégorie (Skis, Chaussures, Accessoires) |
| unit_price | DECIMAL(10,2) | Prix de vente |
| stock_qty | INT | Quantité disponible |
| last_update | DATETIME | Dernière mise à jour du stock |
Implémentation du Back-end
Le point d'entrée de l'application configure le scan des mapperrs MyBatis et initialise le contexte Spring Boot.
package fr.skishop.api;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@SpringBootApplication
@MapperScan("fr.skishop.api.repository")
public class SkiGearApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(SkiGearApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(SkiGearApplication.class);
}
}
Gestion des Comptes Utilisateurs
Le contrôleur suivant gère l'authentification et l'enregistrement des clients via des services REST.
package fr.skishop.api.controller;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import fr.skishop.api.entity.UserAccount;
import fr.skishop.api.service.AccountService;
import fr.skishop.api.security.TokenProvider;
import fr.skishop.api.utils.JsonResponse;
@RestController
@RequestMapping("/api/accounts")
public class AccountController {
@Autowired
private AccountService accountService;
@Autowired
private TokenProvider tokenProvider;
@PostMapping("/auth")
public JsonResponse authenticate(@RequestParam String login, @RequestParam String secret) {
UserAccount account = accountService.selectOne(
new EntityWrapper<UserAccount>().eq("account_name", login)
);
if (account == null || !account.getSecurePwd().equals(secret)) {
return JsonResponse.error("Identifiants invalides");
}
String authToken = tokenProvider.createToken(account.getIdUser(), login, "client");
return JsonResponse.ok().put("token", authToken);
}
@PostMapping("/signup")
public JsonResponse register(@RequestBody UserAccount newUser) {
UserAccount existing = accountService.selectOne(
new EntityWrapper<UserAccount>().eq("account_name", newUser.getAccountName())
);
if (existing != null) {
return JsonResponse.error("Ce nom d'utilisateur est déjà utilisé");
}
newUser.setCreatedAt(new Date());
accountService.insert(newUser);
return JsonResponse.ok("Inscription réussie");
}
@GetMapping("/profile")
public JsonResponse getProfile(HttpServletRequest request) {
Long userId = (Long) request.getSession().getAttribute("userId");
UserAccount profile = accountService.selectById(userId);
return JsonResponse.ok().put("data", profile);
}
@DeleteMapping("/remove")
public JsonResponse deleteAccounts(@RequestBody Long[] ids) {
accountService.deleteBatchIds(Arrays.asList(ids));
return JsonResponse.ok("Suppression effectuée");
}
}
Fonctionnalités Principales du Système
L'application est divisée en plusieurs modules fonctionnels pour assurer une gestion complète du cycle de vente :
- Catalogue Interactif : Affichage dynamique des produits avec filtrage par catégorie et recherche textuelle, propulsé par Vue.js.
- Gestion du Panier : Persistance locale des choix de l'utilisateur avant la validation de la commande.
- Traitement des Commandes : Gestion des transactions, calcul automatique du montant total et mise à jour en temps réel des stocks MySQL.
- Interface d'Administration : Tableau de bord permettant aux gestionnaires de modifier les prrix, d'ajouter de nouveaux équipements et de suivre les statuts de livraison.