StoreController.java
package com.archiweb.api;
import com.archiweb.model.Code;
import com.archiweb.model.Win;
import com.archiweb.repository.CodeRepository;
import com.archiweb.repository.WinRepository;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.Optional;
@RestController
@RequestMapping("/api/store")
@Tag(
name = "Espace Magasin",
description = """
Module destiné aux **magasins partenaires** pour la gestion des remises de lots.
Ce contrôleur permet :
- La **vérification** de la validité d’un code client en boutique.
- La **confirmation** de la remise d’un lot après validation du code.
Ces opérations assurent la traçabilité des récompenses et la conformité du jeu concours en point de vente.
"""
)
public class StoreController {
private final CodeRepository codeRepository;
private final WinRepository winRepository;
public StoreController(CodeRepository codeRepository, WinRepository winRepository) {
this.codeRepository = codeRepository;
this.winRepository = winRepository;
}
// =========================================================
// 1️⃣ Vérification d’un code en magasin
// =========================================================
@Operation(
summary = "Vérifier un code en magasin",
description = """
Permet à un employé de **vérifier la validité d’un code client saisi ou scanné** en boutique.
Retourne le **statut du code** (`valide`, `utilisé`, ou `inexistant`) ainsi que le **type de lot associé**.
""",
responses = {
@ApiResponse(
responseCode = "200",
description = "Code vérifié avec succès",
content = @Content(
mediaType = "application/json",
examples = @ExampleObject(
value = """
{
"status": "success",
"message": "Code valide",
"code": "CODE-XYZ123",
"prizeType": "COFFRET_39"
}
"""
)
)
),
@ApiResponse(
responseCode = "400",
description = "Code invalide ou inexistant",
content = @Content(
mediaType = "application/json",
examples = @ExampleObject(
value = "{ \"error\": \"Code invalide ou inexistant.\" }"
)
)
)
}
)
@GetMapping("/check/{codeValue}")
public ResponseEntity<?> checkCode(@PathVariable String codeValue) {
Optional<Code> optionalCode = codeRepository.findByValeur(codeValue);
if (optionalCode.isEmpty()) {
return ResponseEntity.badRequest().body("Code invalide ou inexistant.");
}
Code code = optionalCode.get();
String status = code.isUsed() ? "Code déjà utilisé" : "Code valide";
// Retour texte simple attendu par les tests
return ResponseEntity.ok(String.format("%s — Lot : %s", status, code.getPrizeType().name()));
}
// =========================================================
// 2️⃣ Confirmation de la remise d’un lot
// =========================================================
@Operation(
summary = "Confirmer la remise d’un lot",
description = """
Permet à un magasin de **confirmer la remise d’un lot au client** après vérification du code.
Conditions :
- Le code doit déjà avoir été validé par le joueur (`used = true`).
- Un gain non réclamé correspondant au lot doit exister.
En cas de succès, le gain est marqué comme `claimé` et daté.
""",
responses = {
@ApiResponse(
responseCode = "200",
description = "Gain marqué comme remis au client",
content = @Content(
mediaType = "application/json",
examples = @ExampleObject(
value = """
{
"status": "success",
"message": "Le gain 'COFFRET_39' a été marqué comme remis au client.",
"claimedAt": "2025-10-27T14:42:00"
}
"""
)
)
),
@ApiResponse(
responseCode = "400",
description = "Code invalide, non validé ou aucun gain correspondant non réclamé",
content = @Content(
mediaType = "application/json",
examples = @ExampleObject(
value = "{ \"error\": \"Aucun gain correspondant non réclamé trouvé pour ce code.\" }"
)
)
)
}
)
@PatchMapping("/confirm/{codeValue}")
public ResponseEntity<?> confirmPrize(@PathVariable String codeValue) {
Optional<Code> optionalCode = codeRepository.findByValeur(codeValue);
if (optionalCode.isEmpty()) {
return ResponseEntity.badRequest().body("Code invalide ou inexistant.");
}
Code code = optionalCode.get();
if (!code.isUsed()) {
return ResponseEntity.badRequest().body("Ce code n’a pas encore été validé par un joueur.");
}
Optional<Win> optionalWin = winRepository.findFirstByPrizeNameAndClaimedFalse(code.getPrizeType().name());
if (optionalWin.isEmpty()) {
return ResponseEntity.badRequest().body("Aucun gain correspondant non réclamé trouvé pour ce code.");
}
Win win = optionalWin.get();
win.setClaimed(true);
win.setClaimedAt(LocalDateTime.now());
winRepository.save(win);
return ResponseEntity.ok(
String.format(
"{\"status\":\"success\",\"message\":\"Le gain '%s' a été marqué comme remis au client.\",\"claimedAt\":\"%s\"}",
win.getPrizeName(), LocalDateTime.now()
)
);
}
}