ShopFlow is a B2C e-commerce platform: sellers publish products, customers browse the catalog, manage a cart, and place orders with simulated payment. It is built with a Spring Boot 3 / Jakarta EE backend and a Next.js 14 frontend and covers the full pedagogical scope of the subject: REST API, complex JPA relations, business rules (stock, orders, coupons), role-based JWT security, and a dynamic UI consuming the API with guarded routes.
- Features
- Architecture
- Technology stack
- Project layout
- Prerequisites
- Running locally
- Demo accounts
- REST endpoints
- Swagger / OpenAPI
- Testing & coverage
- Environment variables
- ADMIN — global platform management (users, categories, coupons, moderation).
- SELLER — manages their shop, products and received orders.
- CUSTOMER — browses the catalog, manages the cart, places orders, reviews products.
- Catalog — products with variants (size/color + per-variant stock), categories
(self-referencing tree), multi-image support, soft delete, promo prices,
full-text search (
/api/products/search), top-selling list, low-stock alerts. - Users & auth — customer / seller registration, login with JWT (access + refresh token), logout, profile, multiple addresses, password reset by token, account activation/deactivation by ADMIN.
- Cart — persistent per-user cart, add/update/remove items, coupon code, subtotal + shipping + total TTC calculation.
- Orders — checkout from the cart with final stock check, unique order number
(
ORD-YYYY-XXXXX), status workflowPENDING → PAID → PROCESSING → SHIPPED → DELIVERED, cancellation with stock restoration (only inPENDING/PAID), simulated Stripe payment. - Reviews — customers rate purchased products (1-5 + comment), ADMIN moderation, automatic average-rating computation.
- Dashboards — ADMIN (global revenue, top products/sellers, pending orders), SELLER (revenue, low-stock alerts, recent orders), CUSTOMER (my orders, my reviews).
- Coupons — percent or fixed-amount, expiration date, max usages, uniqueness on code.
- Security — Spring Security 6 with JWT filter,
@PreAuthorizeper endpoint, BCrypt password hashing, CORS configured for the frontend.
Home, catalog with filters, product detail, cart, checkout, customer profile (addresses, orders, reviews), admin dashboard (users, reviews, stock), seller dashboard (revenue, products, orders), login/register/forgot-password.
┌──────────────────────┐ HTTP JSON + Bearer JWT ┌─────────────────────────┐
│ Next.js 14 frontend │ ─────────────────────────────────▶ │ Spring Boot 3 backend │
│ (App Router, TS) │ ◀───────────────────────────────── │ JWT + JPA + Swagger │
└──────────────────────┘ └────────────┬────────────┘
│
┌────────▼────────┐
│ H2 (dev/test) │
│ or PostgreSQL │
└─────────────────┘
The backend follows the mandatory layered architecture:
controller → service (@Transactional) → repository (Spring Data JPA) → entity (Jakarta Persistence).
DTOs are mapped to/from entities via MapStruct. Global error handling lives
in GlobalExceptionHandler (@ControllerAdvice).
| Layer | Technology |
|---|---|
| Language | Java 17 |
| Framework | Spring Boot 3.3.4, Spring MVC, Spring Data JPA, Spring Security 6 |
| Persistence | Jakarta Persistence 3, Hibernate, H2 (default) or PostgreSQL |
| Validation | Jakarta Bean Validation 3 (@Valid, @NotBlank, @Min, ...) |
| Security | Spring Security 6 + JWT (jjwt 0.12.5), BCrypt |
| Documentation | Springdoc OpenAPI 2.6 (Swagger UI) |
| Mapping | MapStruct 1.6 |
| Utilities | Lombok 1.18 |
| Tests | JUnit 5, Mockito, AssertJ, JaCoCo (≥70% service-layer coverage enforced) |
| Build | Maven |
| Layer | Technology |
|---|---|
| Framework | Next.js 14 (App Router) + TypeScript |
| Styling | TailwindCSS (responsive, mobile-first) |
| State | Zustand |
| HTTP | Axios with request interceptor (Bearer JWT) + 401 refresh-token auto-retry |
| Auth | Client-side AuthGuard component + route-group layouts |
| Tooling | ESLint, Next.js build |
java_project/
├── shopflow-backend/ # Spring Boot 3 REST API
│ ├── src/main/java/com/shopflow/
│ │ ├── config/ # SecurityConfig, OpenApiConfig, DatabaseSeeder,
│ │ │ # OrderStatusMigrationRunner
│ │ ├── controller/ # REST controllers (11 controllers)
│ │ ├── dto/ # Request / Response DTOs (separate from entities)
│ │ ├── entity/ # 16 JPA entities (User, Product, Cart, Order, ...)
│ │ ├── exception/ # Custom exceptions + @ControllerAdvice
│ │ ├── mapper/ # MapStruct mappers
│ │ ├── repository/ # Spring Data JPA + JpaSpecificationExecutor
│ │ ├── security/ # JwtUtils, JwtAuthenticationFilter, UserDetails
│ │ └── service/ # 12 services (@Transactional business logic)
│ ├── src/main/resources/application.yml
│ ├── src/test/java/com/shopflow/service/ # JUnit 5 / Mockito test suite
│ └── pom.xml # JaCoCo plugin, coverage threshold 70%
│
├── shopflow-frontend/ # Next.js 14 UI
│ ├── src/app/ # Pages (App Router): /, /products, /cart,
│ │ # /checkout, /profile, /dashboard, /login, ...
│ ├── src/components/ # Reusable: ProductCard, OrderStatusBadge,
│ │ # RatingStars, AuthGuard, KpiCard, ...
│ ├── src/lib/api.ts # Axios client + interceptor + token refresh
│ ├── src/store/ # Zustand stores (auth, cart, ...)
│ └── package.json
│
├── MiniProjet_ShopFlow.pdf # Subject
├── ShopFlow-Presentation.pptx # Slides
├── start.sh # Helper to launch backend + frontend
└── README.md # This file
- JDK 17+ (Temurin or OpenJDK)
- Maven 3.9+ (or the bundled wrapper, if present)
- Node.js 18+ and npm 9+
- (Optional) PostgreSQL 14+ for production; the default profile uses H2.
cd shopflow-backend
mvn spring-boot:runThe API starts on http://localhost:8080. The H2 console is enabled at
/h2-console (JDBC URL jdbc:h2:file:./data/shopflow, user sa, password password).
A DatabaseSeeder populates the database with demo users, products, categories
and coupons on first boot.
cd shopflow-frontend
npm install
npm run devOpens http://localhost:3000. The frontend is pre-configured to hit the
backend on http://localhost:8080.
bash start.shAll demo accounts share the password password123.
| Role | |
|---|---|
| ADMIN | admin@shopflow.com |
| CUSTOMER | jean.dupont@shopflow.com |
| SELLER | seller@techstore.com |
Sample coupons seeded in DatabaseSeeder:
BIENVENUE10 (10%), SHOPFLOW5 (5€ fixed), etc.
Base URL: http://localhost:8080
| Method | Path | Role | Description |
|---|---|---|---|
| POST | /register |
public | Register customer or seller |
| POST | /login |
public | Returns token + refreshToken |
| POST | /refresh |
public | Renew the access token |
| POST | /logout |
auth | Invalidate the refresh token |
| GET | /me |
auth | Current user profile |
| POST | /forgot-password |
public | Request password-reset token |
| POST | /reset-password |
public | Reset the password with the token |
| Method | Path | Role | Description |
|---|---|---|---|
| GET | / |
public | Paginated list + filters (q, categoryId, sellerId, prixMin, prixMax, promo, noteMin, sort) |
| GET | /{id} |
public | Product detail + variants + reviews + average rating |
| GET | /search?q=... |
public | Full-text search |
| GET | /top-selling |
public | Top 10 best-selling |
| GET | /low-stock |
SELLER/ADMIN | Low-stock products |
| GET | /by-seller/{sellerId} |
public | Products of a seller |
| GET | /my |
SELLER | Products of the logged-in seller |
| POST | / |
SELLER/ADMIN | Create |
| PUT | /{id} |
SELLER/ADMIN | Update |
| POST | /{id}/images |
SELLER/ADMIN | Upload images |
| DELETE | /{id} |
SELLER/ADMIN | Soft delete |
| Method | Path | Role | Description |
|---|---|---|---|
| GET | / |
public | Category tree |
| GET | /all |
public | Flat list |
| POST | / |
ADMIN | Create |
| PUT | /{id} |
ADMIN | Update |
| DELETE | /{id} |
ADMIN | Delete |
| Method | Path | Role | Description |
|---|---|---|---|
| GET | / |
CUSTOMER | Current cart |
| POST | /items |
CUSTOMER | Add an item |
| PUT | /items/{itemId} |
CUSTOMER | Update quantity |
| DELETE | /items/{itemId} |
CUSTOMER | Remove an item |
| POST | /coupon |
CUSTOMER | Apply a coupon |
| DELETE | /coupon |
CUSTOMER | Remove the coupon |
| Method | Path | Role | Description |
|---|---|---|---|
| POST | / |
CUSTOMER | Place an order from the cart |
| GET | /my |
CUSTOMER | My orders |
| GET | /{id} |
auth | Order detail (owner / seller / admin) |
| PUT | /{id}/status |
SELLER/ADMIN | Update status |
| PUT | /{id}/cancel |
CUSTOMER/ADMIN/SELLER | Cancel (only PENDING/PAID) |
| GET | / |
ADMIN | All orders |
| GET | /sales |
SELLER/ADMIN | Sales for the current user |
| Method | Path | Role | Description |
|---|---|---|---|
| POST | / |
CUSTOMER | Post a review (verified purchase) |
| GET | /product/{productId} |
public | Reviews for a product |
| GET | /pending |
ADMIN | Reviews pending moderation |
| PUT | /{id}/approve |
ADMIN | Approve |
| DELETE | /{id} |
ADMIN | Delete |
| Method | Path | Role | Description |
|---|---|---|---|
| GET | / |
ADMIN | List |
| GET | /{id} |
ADMIN | Detail |
| GET | /validate/{code} |
auth | Check validity |
| POST | / |
ADMIN | Create |
| PUT | /{id} |
ADMIN | Update (with uniqueness check on code) |
| DELETE | /{id} |
ADMIN | Soft delete |
| Method | Path | Role | Description |
|---|---|---|---|
| GET | /admin |
ADMIN | Global KPIs |
| GET | /seller |
SELLER/ADMIN | Seller KPIs |
| GET | /customer |
CUSTOMER | Customer KPIs |
Once the backend is running, the Swagger UI is available at:
The OpenAPI JSON is exposed at /v3/api-docs. All protected endpoints expect
an Authorization: Bearer <jwt> header — click Authorize in the UI and
paste the token returned by POST /api/auth/login.
The backend ships a JUnit 5 + Mockito test suite with JaCoCo coverage,
a build-time check enforces ≥ 70 % line coverage on the com.shopflow.service
package — the service layer that carries all business rules.
cd shopflow-backend
mvn testmvn verifyAfter running mvn test, the HTML report is at
shopflow-backend/target/site/jacoco/index.html.
cd shopflow-frontend
npm run lint
npm run buildMost values have sensible defaults in application.yml. Override them via
environment variables (see src/main/resources/application.yml).
| Variable | Default | Description |
|---|---|---|
app.h2.path |
./data/shopflow |
H2 file database path |
jwt.secret |
(base64 sample key) | JWT signing secret (change in production) |
jwt.expiration |
86400000 |
Access-token TTL in ms (24h) |
jwt.refreshExpiration |
604800000 |
Refresh-token TTL in ms (7d) |
app.frontend-url |
http://localhost:3000 |
Frontend origin (used by password reset) |
app.password-reset.expose-token |
true |
In dev, return the reset token in the API response |
STRIPE_SECRET_KEY |
(empty) | Stripe test secret key (optional, payment bonus) |
STRIPE_PUBLIC_KEY |
pk_test_... |
Stripe publishable key |
To run against PostgreSQL, set the standard spring.datasource.* properties
and change spring.jpa.database-platform to PostgreSQLDialect.