🎉 Push every file from windaube computers

This commit is contained in:
2025-06-14 22:38:49 +02:00
parent dab8a636d0
commit 3a7b9aba56
100 changed files with 6220 additions and 809 deletions

10
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,10 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Environment-dependent path to Maven home directory
/mavenHomeManager.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

7
.idea/encodings.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
</component>
</project>

12
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_24" default="true" project-jdk-name="24" project-jdk-type="JavaSDK" />
</project>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@@ -0,0 +1,24 @@
package fr.iut_fbleau.but3.dev62.mylibrary.book;
import java.time.LocalDate;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
@Builder
@Getter
@AllArgsConstructor
public class BookDTO {
private final String isbn;
private final String title;
private final String author;
private final String publisher;
private final LocalDate publicationDate;
private final double price;
private final int stock;
private final List<Category> categories;
private final String description;
private final String language;
}

View File

@@ -0,0 +1,17 @@
package fr.iut_fbleau.but3.dev62.mylibrary.book;
import java.time.LocalDate;
import java.util.List;
public record BookInfo(
String isbn,
String title,
String author,
String publisher,
LocalDate publicationDate,
double price,
int stock,
List<Category> categories,
String description,
String language
) {}

View File

@@ -0,0 +1,24 @@
package fr.iut_fbleau.but3.dev62.mylibrary.book;
public enum Category {
FICTION,
NON_FICTION,
SCIENCE_FICTION,
FANTASY,
MYSTERY,
THRILLER,
ROMANCE,
BIOGRAPHY,
HISTORY,
POETRY,
CHILDREN,
YOUNG_ADULT,
SCIENCE,
PHILOSOPHY,
SELF_HELP,
TRAVEL,
COOKING,
ART,
RELIGION,
REFERENCE
}

View File

@@ -0,0 +1,40 @@
package fr.iut_fbleau.but3.dev62.mylibrary.book.converter;
import fr.iut_fbleau.but3.dev62.mylibrary.book.BookDTO;
import fr.iut_fbleau.but3.dev62.mylibrary.book.BookInfo;
import fr.iut_fbleau.but3.dev62.mylibrary.book.entity.Book;
public final class BookConverter {
private BookConverter() {}
public static Book toDomain(BookInfo info) {
return Book.builder()
.isbn(info.isbn())
.title(info.title())
.author(info.author())
.publisher(info.publisher())
.publicationDate(info.publicationDate())
.price(info.price())
.stock(info.stock())
.categories(info.categories())
.description(info.description())
.language(info.language())
.build();
}
public static BookDTO toDTO(Book book) {
return BookDTO.builder()
.isbn(book.getIsbn())
.title(book.getTitle())
.author(book.getAuthor())
.publisher(book.getPublisher())
.publicationDate(book.getPublicationDate())
.price(book.getPrice())
.stock(book.getStock())
.categories(book.getCategories())
.description(book.getDescription())
.language(book.getLanguage())
.build();
}
}

View File

@@ -0,0 +1,33 @@
package fr.iut_fbleau.but3.dev62.mylibrary.book.entity;
import fr.iut_fbleau.but3.dev62.mylibrary.book.Category;
import java.time.LocalDate;
import java.util.List;
import lombok.Builder;
import lombok.Getter;
@Builder
@Getter
public class Book {
private String isbn;
private String title;
private String author;
private String publisher;
private LocalDate publicationDate;
private double price;
private int stock;
private List<Category> categories;
private String description;
private String language;
public void addStock(int quantityToAdd) {
this.stock += quantityToAdd;
}
public void removeStock(int quantityToRemove) {
if (quantityToRemove > this.stock) {
throw new IllegalArgumentException("Pas assez de stock pour retirer : " + quantityToRemove);
}
this.stock -= quantityToRemove;
}
}

View File

@@ -0,0 +1,13 @@
package fr.iut_fbleau.but3.dev62.mylibrary.book.exception;
public class BookNotFoundException extends RuntimeException {
public static final String THE_BOOK_WITH_ISBN_DOES_NOT_EXIST_MESSAGE = "The book with isbn %s does not exist";
public BookNotFoundException(String message) {
super(message);
}
public static BookNotFoundException forIsbn(String isbn) {
return new BookNotFoundException(String.format(THE_BOOK_WITH_ISBN_DOES_NOT_EXIST_MESSAGE, isbn));
}
}

View File

@@ -0,0 +1,7 @@
package fr.iut_fbleau.but3.dev62.mylibrary.book.exception;
public class NotValidBookException extends RuntimeException {
public NotValidBookException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,78 @@
package fr.iut_fbleau.but3.dev62.mylibrary.book.repository;
import fr.iut_fbleau.but3.dev62.mylibrary.book.entity.Book;
import fr.iut_fbleau.but3.dev62.mylibrary.book.Category;
import java.util.*;
import java.util.stream.Collectors;
import lombok.NoArgsConstructor;
@NoArgsConstructor
public final class BookRepository {
private final List<Book> books = new ArrayList<>();
public List<Book> findAll() {
return books;
}
public void deleteAll() {
books.clear();
}
public Book save(Book newBook) {
Optional<Book> optionalBookWithSameIsbn = this.findByIsbn(newBook.getIsbn());
optionalBookWithSameIsbn.ifPresent(books::remove);
books.add(newBook);
return newBook;
}
public Optional<Book> findByIsbn(String isbn) {
return books.stream()
.filter(book -> Objects.equals(book.getIsbn(), isbn))
.findFirst();
}
public boolean existsByIsbn(String isbn) {
return books.stream()
.anyMatch(book -> Objects.equals(book.getIsbn(), isbn));
}
public void delete(Book book) {
books.remove(book);
}
public List<Book> findByTitleContaining(String titlePart) {
return books.stream()
.filter(book -> book.getTitle() != null && book.getTitle().toLowerCase().contains(titlePart.toLowerCase()))
.collect(Collectors.toList());
}
public List<Book> findByAuthor(String author) {
return books.stream()
.filter(book -> book.getAuthor() != null && book.getAuthor().equalsIgnoreCase(author))
.collect(Collectors.toList());
}
public List<Book> findByPublisher(String publisher) {
return books.stream()
.filter(book -> book.getPublisher() != null && book.getPublisher().equalsIgnoreCase(publisher))
.collect(Collectors.toList());
}
public List<Book> findByCategory(Category category) {
return books.stream()
.filter(book -> book.getCategories() != null && book.getCategories().contains(category))
.collect(Collectors.toList());
}
public List<Book> findPublishedAfter(java.time.LocalDate date) {
return books.stream()
.filter(book -> book.getPublicationDate() != null && book.getPublicationDate().isAfter(date))
.collect(Collectors.toList());
}
public List<Book> findByPriceRange(double min, double max) {
return books.stream()
.filter(book -> book.getPrice() >= min && book.getPrice() <= max)
.collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,163 @@
package fr.iut_fbleau.but3.dev62.mylibrary.book.usecase;
import fr.iut_fbleau.but3.dev62.mylibrary.book.*;
import fr.iut_fbleau.but3.dev62.mylibrary.book.converter.BookConverter;
import fr.iut_fbleau.but3.dev62.mylibrary.book.entity.Book;
import fr.iut_fbleau.but3.dev62.mylibrary.book.exception.BookNotFoundException;
import fr.iut_fbleau.but3.dev62.mylibrary.book.exception.NotValidBookException;
import fr.iut_fbleau.but3.dev62.mylibrary.book.repository.BookRepository;
import fr.iut_fbleau.but3.dev62.mylibrary.book.validator.BookValidator;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;
public final class BookUseCase {
private final BookRepository repository;
public BookUseCase(BookRepository repository) {
this.repository = repository;
}
public String registerBook(BookInfo info) throws NotValidBookException {
BookValidator.validate(info);
if (repository.existsByIsbn(info.isbn())) {
throw new NotValidBookException("A book with this ISBN already exists");
}
Book book = BookConverter.toDomain(info);
Book stored = repository.save(book);
return stored.getIsbn();
}
public BookDTO updateBook(String isbn, BookInfo data) throws BookNotFoundException, NotValidBookException {
BookValidator.validate(data);
ensureBookExists(isbn);
Book updated = Book.builder()
.isbn(isbn)
.title(data.title())
.author(data.author())
.publisher(data.publisher())
.publicationDate(data.publicationDate())
.price(data.price())
.stock(data.stock())
.categories(data.categories())
.description(data.description())
.language(data.language())
.build();
return BookConverter.toDTO(repository.save(updated));
}
public int addStock(String isbn, int quantity) throws BookNotFoundException {
Book book = ensureBookExists(isbn);
book.addStock(quantity);
repository.save(book);
return book.getStock();
}
public int removeStock(String isbn, int quantity) throws BookNotFoundException {
Book book = ensureBookExists(isbn);
book.removeStock(quantity);
repository.save(book);
return book.getStock();
}
public void deleteBook(String isbn) throws BookNotFoundException {
Book target = ensureBookExists(isbn);
repository.delete(target);
}
public BookDTO findBookByIsbn(String isbn) throws BookNotFoundException {
return repository.findByIsbn(isbn)
.map(BookConverter::toDTO)
.orElseThrow(() -> new BookNotFoundException(isbn));
}
public List<BookDTO> findBooksByAuthor(String author) {
return repository.findByAuthor(author)
.stream()
.map(BookConverter::toDTO)
.collect(Collectors.toList());
}
public List<BookDTO> findBooksByCategory(Category category) {
return repository.findByCategory(category)
.stream()
.map(BookConverter::toDTO)
.collect(Collectors.toList());
}
public List<BookDTO> findBooksByTitleContaining(String title) {
return repository.findByTitleContaining(title)
.stream()
.map(BookConverter::toDTO)
.collect(Collectors.toList());
}
public List<BookDTO> findBooksByPublisher(String publisher) {
return repository.findByPublisher(publisher)
.stream()
.map(BookConverter::toDTO)
.collect(Collectors.toList());
}
public List<BookDTO> findBooksPublishedAfter(LocalDate date) {
return repository.findPublishedAfter(date)
.stream()
.map(BookConverter::toDTO)
.collect(Collectors.toList());
}
public List<BookDTO> findBooksByPriceRange(double min, double max) {
return repository.findByPriceRange(min, max)
.stream()
.map(BookConverter::toDTO)
.collect(Collectors.toList());
}
public Map<String, Object> findBooksPageSorted(int page, int size, String sortBy) {
List<Book> books = repository.findAll();
books.sort(Comparator.comparing(book -> {
switch (sortBy.toLowerCase()) {
case "title":
case "titre":
return book.getTitle() == null ? "" : book.getTitle().toLowerCase();
case "author":
case "auteur":
return book.getAuthor() == null ? "" : book.getAuthor().toLowerCase();
case "publisher":
case "editeur":
return book.getPublisher() == null ? "" : book.getPublisher().toLowerCase();
default:
return book.getTitle() == null ? "" : book.getTitle().toLowerCase();
}
}));
int total = books.size();
int pages = (int) Math.ceil((double) total / size);
int start = Math.min(page * size, total);
int end = Math.min(start + size, total);
List<BookDTO> content = books.subList(start, end)
.stream()
.map(BookConverter::toDTO)
.collect(Collectors.toList());
Map<String, Object> result = new HashMap<>();
result.put("content", content);
result.put("totalElements", total);
result.put("totalPages", pages);
return result;
}
private Book ensureBookExists(String isbn) throws BookNotFoundException {
return repository.findByIsbn(isbn)
.orElseThrow(() -> new BookNotFoundException(isbn));
}
}

View File

@@ -0,0 +1,65 @@
package fr.iut_fbleau.but3.dev62.mylibrary.book.validator;
import fr.iut_fbleau.but3.dev62.mylibrary.book.BookInfo;
import fr.iut_fbleau.but3.dev62.mylibrary.book.exception.NotValidBookException;
public final class BookValidator {
public static final String ERROR_ISBN_NULL = "ISBN cannot be null";
public static final String ERROR_INVALID_ISBN = "ISBN is not valid";
public static final String ERROR_TITLE_EMPTY = "Title cannot be empty";
public static final String ERROR_AUTHOR_EMPTY = "Author cannot be empty";
public static final String ERROR_NEGATIVE_PRICE = "Price must be positive";
public static final String ERROR_NEGATIVE_STOCK = "Stock cannot be negative";
public static final String ERROR_PUBLISHER_EMPTY = "Publisher cannot be empty";
public static final String ERROR_PUBLICATION_DATE_NULL = "Publication date cannot be null";
public static final String ERROR_CATEGORIES_EMPTY = "Categories list cannot be empty";
public static final String ERROR_DESCRIPTION_EMPTY = "Description cannot be empty";
public static final String ERROR_LANGUAGE_EMPTY = "Language cannot be empty";
private BookValidator() {
// Prevent instantiation
}
public static void validate(BookInfo info) throws NotValidBookException {
checkPrice(info);
checkIsbn(info);
checkTitle(info);
checkAuthor(info);
checkStock(info);
}
private static void checkIsbn(BookInfo info) throws NotValidBookException {
String isbn = info.isbn();
if (isbn == null) {
throw new NotValidBookException(ERROR_ISBN_NULL);
}
if (!isbn.matches("\\d{13}")) {
throw new NotValidBookException(ERROR_INVALID_ISBN);
}
}
private static void checkTitle(BookInfo info) throws NotValidBookException {
if (info.title() == null || info.title().isBlank()) {
throw new NotValidBookException(ERROR_TITLE_EMPTY);
}
}
private static void checkAuthor(BookInfo info) throws NotValidBookException {
if (info.author() == null || info.author().isBlank()) {
throw new NotValidBookException(ERROR_AUTHOR_EMPTY);
}
}
private static void checkPrice(BookInfo info) throws NotValidBookException {
if (info.price() < 0) {
throw new NotValidBookException(ERROR_NEGATIVE_PRICE);
}
}
private static void checkStock(BookInfo info) throws NotValidBookException {
if (info.stock() < 0) {
throw new NotValidBookException(ERROR_NEGATIVE_STOCK);
}
}
}

View File

@@ -3,28 +3,30 @@ package fr.iut_fbleau.but3.dev62.mylibrary.customer.converter;
import fr.iut_fbleau.but3.dev62.mylibrary.customer.CustomerDTO;
import fr.iut_fbleau.but3.dev62.mylibrary.customer.CustomerInfo;
import fr.iut_fbleau.but3.dev62.mylibrary.customer.entity.Customer;
import java.util.UUID;
public final class CustomerConverter {
private CustomerConverter(){
private CustomerConverter() {
// util class
}
public static Customer toDomain(CustomerInfo newCustomer) {
return Customer.builder()
.firstName(newCustomer.firstName())
.lastName(newCustomer.lastName())
.phoneNumber(newCustomer.phoneNumber())
.loyaltyPoints(0)
.build();
.id(UUID.randomUUID()) // ← génération automatique
.firstName(newCustomer.firstName())
.lastName(newCustomer.lastName())
.phoneNumber(newCustomer.phoneNumber())
.loyaltyPoints(0)
.build();
}
public static CustomerDTO toDTO(Customer customer) {
return CustomerDTO.builder()
.id(customer.getId())
.firstName(customer.getFirstName())
.lastName(customer.getLastName())
.phoneNumber(customer.getPhoneNumber())
.loyaltyPoints(customer.getLoyaltyPoints())
.build();
.id(customer.getId())
.firstName(customer.getFirstName())
.lastName(customer.getLastName())
.phoneNumber(customer.getPhoneNumber())
.loyaltyPoints(customer.getLoyaltyPoints())
.build();
}
}

View File

@@ -14,68 +14,58 @@ import java.util.UUID;
public final class CustomerUseCase {
private final CustomerRepository customerRepository;
private final CustomerRepository repo;
public CustomerUseCase(CustomerRepository customerRepository) {
this.customerRepository = customerRepository;
public CustomerUseCase(CustomerRepository repo) {
this.repo = repo;
}
public UUID registerCustomer(CustomerInfo newCustomer) throws NotValidCustomerException {
CustomerValidator.validate(newCustomer);
Customer customerToRegister = CustomerConverter.toDomain(newCustomer);
Customer customerToRegistered = customerRepository.save(customerToRegister);
return customerToRegistered.getId();
public Optional<CustomerDTO> getByPhone(String phone) {
return repo.findByPhoneNumber(phone).map(CustomerConverter::toDTO);
}
public Optional<CustomerDTO> findCustomerByPhoneNumber(String phoneNumber) {
Optional<Customer> optionalCustomer = customerRepository.findByPhoneNumber(phoneNumber);
return optionalCustomer.map(CustomerConverter::toDTO);
public UUID create(CustomerInfo input) throws NotValidCustomerException {
CustomerValidator.validate(input);
Customer newCustomer = CustomerConverter.toDomain(input);
Customer saved = repo.save(newCustomer);
return saved.getId();
}
public CustomerDTO updateCustomer(UUID uuid, CustomerInfo customerInfo)
throws CustomerNotFoundException, NotValidCustomerException {
CustomerValidator.validate(customerInfo);
Customer customerByUUID = getCustomerIfDoesNotExistThrowCustomerNotFoundException(
uuid);
Customer customer = Customer.builder()
.id(uuid)
.firstName(customerInfo.firstName())
.lastName(customerInfo.lastName())
.phoneNumber(customerInfo.phoneNumber())
.loyaltyPoints(customerByUUID.getLoyaltyPoints())
.build();
Customer updatedCustomer = customerRepository.save(customer);
return CustomerConverter.toDTO(updatedCustomer);
public int increasePoints(UUID id, int points) throws CustomerNotFoundException {
Customer c = resolveOrFail(id);
c.addLoyaltyPoints(points);
repo.save(c);
return c.getLoyaltyPoints();
}
public void deleteCustomer(UUID uuid) throws CustomerNotFoundException {
Customer customerToDelete = getCustomerIfDoesNotExistThrowCustomerNotFoundException(uuid);
this.customerRepository.delete(customerToDelete);
public int decreasePoints(UUID id, int points)
throws CustomerNotFoundException, IllegalCustomerPointException {
Customer c = resolveOrFail(id);
c.removeLoyaltyPoints(points);
repo.save(c);
return c.getLoyaltyPoints();
}
public int addLoyaltyPoints(UUID uuid, int loyaltyPointToAdd) throws CustomerNotFoundException {
Customer customerToAddLoyaltyPoints = getCustomerIfDoesNotExistThrowCustomerNotFoundException(
uuid);
customerToAddLoyaltyPoints.addLoyaltyPoints(loyaltyPointToAdd);
customerRepository.save(customerToAddLoyaltyPoints);
return customerToAddLoyaltyPoints.getLoyaltyPoints();
public void remove(UUID id) throws CustomerNotFoundException {
Customer c = resolveOrFail(id);
repo.delete(c);
}
public int subtractLoyaltyPoints(UUID uuid, int loyaltyPointToRemove)
throws CustomerNotFoundException, IllegalCustomerPointException {
Customer customerToSubtractLoyaltyPoints = getCustomerIfDoesNotExistThrowCustomerNotFoundException(
uuid);
customerToSubtractLoyaltyPoints.removeLoyaltyPoints(loyaltyPointToRemove);
customerRepository.save(customerToSubtractLoyaltyPoints);
return customerToSubtractLoyaltyPoints.getLoyaltyPoints();
public CustomerDTO modify(UUID id, CustomerInfo input)
throws CustomerNotFoundException, NotValidCustomerException {
CustomerValidator.validate(input);
Customer existing = resolveOrFail(id);
Customer updated = Customer.builder()
.id(id)
.firstName(input.firstName())
.lastName(input.lastName())
.phoneNumber(input.phoneNumber())
.loyaltyPoints(existing.getLoyaltyPoints())
.build();
return CustomerConverter.toDTO(repo.save(updated));
}
private Customer getCustomerIfDoesNotExistThrowCustomerNotFoundException(UUID uuid)
throws CustomerNotFoundException {
Optional<Customer> optionalCustomerById = customerRepository.findById(uuid);
if (optionalCustomerById.isEmpty()) {
throw new CustomerNotFoundException(uuid);
}
return optionalCustomerById.get();
private Customer resolveOrFail(UUID id) throws CustomerNotFoundException {
return repo.findById(id).orElseThrow(() -> new CustomerNotFoundException(id));
}
}

View File

@@ -5,40 +5,37 @@ import fr.iut_fbleau.but3.dev62.mylibrary.customer.exception.NotValidCustomerExc
public final class CustomerValidator {
public static final String PHONE_NUMBER_IS_NOT_VALID = "Phone number is not valid";
public static final String LAST_NAME_CANNOT_BE_BLANK = "Last name cannot be blank";
public static final String FIRST_NAME_CANNOT_BE_BLANK = "First name cannot be blank";
public static final String PHONE_NUMBER_REGEX = "0([67])\\d{8}";
public static final String ERROR_PHONE_INVALID = "Phone number is not valid";
public static final String ERROR_LASTNAME_EMPTY = "Last name cannot be blank";
public static final String ERROR_FIRSTNAME_EMPTY = "First name cannot be blank";
public static final String PHONE_PATTERN = "0([67])\\d{8}";
private CustomerValidator() {
private CustomerValidator() {}
public static void check(CustomerInfo input) throws NotValidCustomerException {
ensureFirstName(input);
ensureLastName(input);
ensurePhone(input);
}
public static void validate(CustomerInfo newCustomer) throws NotValidCustomerException {
validateFirstName(newCustomer);
validateLastName(newCustomer);
validatePhoneNumber(newCustomer);
}
private static void validatePhoneNumber(CustomerInfo newCustomer)
throws NotValidCustomerException {
if (newCustomer.phoneNumber().isBlank()) {
private static void ensurePhone(CustomerInfo input) throws NotValidCustomerException {
if (input.phoneNumber().isBlank()) {
throw new NotValidCustomerException("Phone number cannot be blank");
}
if (!newCustomer.phoneNumber().matches(PHONE_NUMBER_REGEX)) {
throw new NotValidCustomerException(PHONE_NUMBER_IS_NOT_VALID);
if (!input.phoneNumber().matches(PHONE_PATTERN)) {
throw new NotValidCustomerException(ERROR_PHONE_INVALID);
}
}
private static void validateLastName(CustomerInfo newCustomer) throws NotValidCustomerException {
if (newCustomer.lastName().isBlank()) {
throw new NotValidCustomerException(LAST_NAME_CANNOT_BE_BLANK);
private static void ensureLastName(CustomerInfo input) throws NotValidCustomerException {
if (input.lastName().isBlank()) {
throw new NotValidCustomerException(ERROR_LASTNAME_EMPTY);
}
}
private static void validateFirstName(CustomerInfo newCustomer) throws NotValidCustomerException {
if (newCustomer.firstName().isBlank()) {
throw new NotValidCustomerException(FIRST_NAME_CANNOT_BE_BLANK);
private static void ensureFirstName(CustomerInfo input) throws NotValidCustomerException {
if (input.firstName().isBlank()) {
throw new NotValidCustomerException(ERROR_FIRSTNAME_EMPTY);
}
}
}

View File

@@ -0,0 +1,14 @@
package fr.iut_fbleau.but3.dev62.mylibrary.order;
import lombok.Builder;
import lombok.Getter;
@Builder
@Getter
public class AddressDTO {
private final String street;
private final String city;
private final String postalCode;
private final String country;
}

View File

@@ -0,0 +1,19 @@
package fr.iut_fbleau.but3.dev62.mylibrary.order;
import lombok.Builder;
import lombok.Getter;
import java.util.List;
import java.util.UUID;
@Builder
@Getter
public class OrderDTO {
private final UUID id;
private final UUID customerId;
private final String paymentMethod;
private final List<OrderLineDTO> orderLines;
private final AddressDTO shippingAddress;
private final double totalPrice;
private final double totalPriceToPay;
}

View File

@@ -0,0 +1,16 @@
package fr.iut_fbleau.but3.dev62.mylibrary.order;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
@Builder
public class OrderInfo {
private String customerId;
private String paymentMethod;
private List<OrderLineDTO> orderLines;
private AddressDTO address;
}

View File

@@ -0,0 +1,12 @@
package fr.iut_fbleau.but3.dev62.mylibrary.order;
import lombok.Builder;
import lombok.Getter;
@Builder
@Getter
public class OrderLineDTO {
private final String bookId;
private final int quantity;
}

View File

@@ -0,0 +1,6 @@
package fr.iut_fbleau.but3.dev62.mylibrary.order;
public enum PaymentMethod {
CREDIT_CARD,
LOYALTY_POINTS;
}

View File

@@ -0,0 +1,97 @@
package fr.iut_fbleau.but3.dev62.mylibrary.order.converter;
import fr.iut_fbleau.but3.dev62.mylibrary.order.*;
import fr.iut_fbleau.but3.dev62.mylibrary.order.entity.Address;
import fr.iut_fbleau.but3.dev62.mylibrary.order.entity.Order;
import fr.iut_fbleau.but3.dev62.mylibrary.order.entity.OrderLine;
import java.util.UUID;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
public final class OrderConverter {
private OrderConverter() {
throw new AssertionError("This utility class should not be instantiated");
}
public static Order toDomain(OrderInfo info) {
if (info == null) return null;
return Order.builder()
.customerId(Optional.ofNullable(info.getCustomerId())
.map(UUID::fromString)
.orElse(null))
.paymentMethod(Optional.ofNullable(info.getPaymentMethod())
.map(PaymentMethod::valueOf)
.orElse(null))
.orderLines(convertOrderLines(info.getOrderLines()))
.shippingAddress(convertAddress(info.getAddress()))
.totalPrice(0.0)
.build();
}
public static OrderDTO toDTO(Order order) {
if (order == null) return null;
return OrderDTO.builder()
.id(order.getId())
.customerId(order.getCustomerId())
.paymentMethod(Optional.ofNullable(order.getPaymentMethod())
.map(PaymentMethod::name)
.orElse(null))
.orderLines(convertOrderLinesToDTO(order.getOrderLines()))
.shippingAddress(convertAddressToDTO(order.getShippingAddress()))
.totalPrice(order.getTotalPrice())
.totalPriceToPay(order.getTotalPriceToPay())
.build();
}
private static Address convertAddress(AddressDTO addressDTO) {
return Optional.ofNullable(addressDTO)
.map(addr -> Address.builder()
.street(addr.getStreet())
.city(addr.getCity())
.postalCode(addr.getPostalCode())
.country(addr.getCountry())
.build())
.orElse(null);
}
private static AddressDTO convertAddressToDTO(Address address) {
return Optional.ofNullable(address)
.map(addr -> AddressDTO.builder()
.street(addr.getStreet())
.city(addr.getCity())
.postalCode(addr.getPostalCode())
.country(addr.getCountry())
.build())
.orElse(null);
}
private static List<OrderLineDTO> convertOrderLinesToDTO(List<OrderLine> orderLines) {
return Optional.ofNullable(orderLines)
.map(lines -> lines.stream()
.filter(Objects::nonNull)
.map(line -> OrderLineDTO.builder()
.bookId(line.getBookId())
.quantity(line.getQuantity())
.build())
.toList())
.orElse(null);
}
private static List<OrderLine> convertOrderLines(List<OrderLineDTO> orderLines) {
return Optional.ofNullable(orderLines)
.map(lines -> lines.stream()
.filter(Objects::nonNull)
.map(line -> OrderLine.builder()
.bookId(line.getBookId())
.quantity(line.getQuantity())
.build())
.toList())
.orElse(new ArrayList<>());
}
}

View File

@@ -0,0 +1,14 @@
package fr.iut_fbleau.but3.dev62.mylibrary.order.entity;
import lombok.Builder;
import lombok.Getter;
import lombok.AllArgsConstructor;
@Getter
@Builder
public class Address {
private final String street;
private final String city;
private final String postalCode;
private final String country;
}

View File

@@ -0,0 +1,19 @@
package fr.iut_fbleau.but3.dev62.mylibrary.order.entity;
import fr.iut_fbleau.but3.dev62.mylibrary.order.PaymentMethod;
import lombok.Builder;
import lombok.Getter;
import java.util.List;
import java.util.UUID;
@Getter
@Builder
public class Order {
private final UUID id;
private final UUID customerId;
private final PaymentMethod paymentMethod;
private final List<OrderLine> orderLines;
private final Address shippingAddress;
private final double totalPrice;
private final double totalPriceToPay;
}

View File

@@ -0,0 +1,12 @@
package fr.iut_fbleau.but3.dev62.mylibrary.order.entity;
import lombok.Builder;
import lombok.Getter;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
@Getter
@Builder
public class OrderLine {
private final String bookId;
private final int quantity;
}

View File

@@ -0,0 +1,7 @@
package fr.iut_fbleau.but3.dev62.mylibrary.order.exception;
public class IllegalOrderPointException extends RuntimeException {
public IllegalOrderPointException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,7 @@
package fr.iut_fbleau.but3.dev62.mylibrary.order.exception;
public class InvalidPaymentMethodException extends RuntimeException {
public InvalidPaymentMethodException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,7 @@
package fr.iut_fbleau.but3.dev62.mylibrary.order.exception;
public class NotValidOrderException extends RuntimeException {
public NotValidOrderException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,8 @@
package fr.iut_fbleau.but3.dev62.mylibrary.order.exception;
public class OrderNotFoundException extends RuntimeException {
public OrderNotFoundException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,7 @@
package fr.iut_fbleau.but3.dev62.mylibrary.order.exception;
public class OrderQuantityException extends RuntimeException {
public OrderQuantityException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,7 @@
package fr.iut_fbleau.but3.dev62.mylibrary.order.exception;
public class WrongAddressException extends RuntimeException {
public WrongAddressException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,60 @@
package fr.iut_fbleau.but3.dev62.mylibrary.order.repository;
import fr.iut_fbleau.but3.dev62.mylibrary.order.entity.Order;
import java.util.*;
import lombok.NoArgsConstructor;
@NoArgsConstructor
public final class OrderRepository {
private final List<Order> orders = new ArrayList<>();
public void deleteAll() {
orders.clear();
}
public Optional<Order> findById(UUID id) {
return this.orders.stream()
.filter(order -> Objects.equals(order.getId(), id))
.findFirst();
}
public boolean existsById(UUID id) {
return this.orders.stream()
.anyMatch(order -> Objects.equals(order.getId(), id));
}
public void delete(Order order) {
this.orders.remove(order);
}
public Order save(Order newOrder) {
if (newOrder.getId() == null) {
Order orderWithId = Order.builder()
.id(UUID.randomUUID())
.customerId(newOrder.getCustomerId())
.paymentMethod(newOrder.getPaymentMethod())
.orderLines(newOrder.getOrderLines())
.shippingAddress(newOrder.getShippingAddress())
.totalPrice(newOrder.getTotalPrice())
.totalPriceToPay(newOrder.getTotalPriceToPay())
.build();
this.orders.add(orderWithId);
return orderWithId;
}
Optional<Order> optionalOrderWithSameId = this.findById(newOrder.getId());
optionalOrderWithSameId.ifPresent(orders::remove);
this.orders.add(newOrder);
return newOrder;
}
public List<Order> findByCustomerId(UUID customerId) {
return this.orders.stream()
.filter(order -> Objects.equals(order.getCustomerId(), customerId))
.toList();
}
public List<Order> findAll() {
return orders;
}
}

View File

@@ -0,0 +1,158 @@
package fr.iut_fbleau.but3.dev62.mylibrary.order.usecase;
import fr.iut_fbleau.but3.dev62.mylibrary.book.exception.BookNotFoundException;
import fr.iut_fbleau.but3.dev62.mylibrary.book.repository.BookRepository;
import fr.iut_fbleau.but3.dev62.mylibrary.customer.exception.CustomerNotFoundException;
import fr.iut_fbleau.but3.dev62.mylibrary.customer.exception.IllegalCustomerPointException;
import fr.iut_fbleau.but3.dev62.mylibrary.customer.repository.CustomerRepository;
import fr.iut_fbleau.but3.dev62.mylibrary.customer.entity.Customer;
import fr.iut_fbleau.but3.dev62.mylibrary.order.*;
import fr.iut_fbleau.but3.dev62.mylibrary.order.converter.OrderConverter;
import fr.iut_fbleau.but3.dev62.mylibrary.order.entity.Order;
import fr.iut_fbleau.but3.dev62.mylibrary.order.exception.*;
import fr.iut_fbleau.but3.dev62.mylibrary.order.repository.OrderRepository;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
public final class OrderUseCase {
private final OrderRepository orderRepository;
private final CustomerRepository customerRepository;
private final BookRepository bookRepository;
public OrderUseCase(OrderRepository orderRepository, CustomerRepository customerRepository, BookRepository bookRepository) {
this.orderRepository = orderRepository;
this.customerRepository = customerRepository;
this.bookRepository = bookRepository;
}
public UUID createOrder(OrderInfo orderInfo) throws CustomerNotFoundException, IllegalCustomerPointException, NotValidOrderException {
validateOrderInfo(orderInfo);
PaymentMethod paymentMethod = parsePaymentMethod(orderInfo.getPaymentMethod());
UUID customerId = parseCustomerId(orderInfo.getCustomerId());
Customer customer = customerRepository.findById(customerId)
.orElseThrow(() -> new CustomerNotFoundException(customerId));
Map<String, fr.iut_fbleau.but3.dev62.mylibrary.book.entity.Book> books = orderInfo.getOrderLines().stream()
.map(line -> bookRepository.findByIsbn(line.getBookId())
.orElseThrow(() -> new BookNotFoundException("Book with ISBN " + line.getBookId() + " was not found")))
.collect(Collectors.toMap(fr.iut_fbleau.but3.dev62.mylibrary.book.entity.Book::getIsbn, b -> b));
validateOrderLines(orderInfo, books);
double totalPrice = calculateTotalPrice(orderInfo, books);
double totalPriceToPay = calculateTotalPriceToPay(orderInfo, books);
Order domainOrder = OrderConverter.toDomain(orderInfo);
Order order = Order.builder()
.customerId(customerId)
.paymentMethod(paymentMethod)
.orderLines(domainOrder.getOrderLines())
.shippingAddress(domainOrder.getShippingAddress())
.totalPrice(totalPrice)
.totalPriceToPay(totalPriceToPay)
.build();
if (paymentMethod == PaymentMethod.LOYALTY_POINTS) {
handleLoyaltyPointsPayment(customer, totalPrice);
}
return orderRepository.save(order).getId();
}
public OrderDTO findOrderById(String orderId) {
UUID uuid = parseOrderId(orderId);
return orderRepository.findById(uuid)
.map(OrderConverter::toDTO)
.orElseThrow(() -> new OrderNotFoundException("Order not found"));
}
public List<OrderDTO> findOrdersByCustomerId(String customerId) throws CustomerNotFoundException {
UUID uuid = parseCustomerId(customerId);
customerRepository.findById(uuid)
.orElseThrow(() -> new CustomerNotFoundException(uuid));
return orderRepository.findByCustomerId(uuid)
.stream()
.map(OrderConverter::toDTO)
.toList();
}
private void validateOrderLines(OrderInfo orderInfo, Map<String, fr.iut_fbleau.but3.dev62.mylibrary.book.entity.Book> books) {
orderInfo.getOrderLines().forEach(line -> {
if (line.getQuantity() <= 0) {
throw new OrderQuantityException("Quantity must be greater than 0 for book " + line.getBookId());
}
var book = books.get(line.getBookId());
if (book.getStock() < line.getQuantity()) {
throw new OrderQuantityException("Insufficient stock for book " + line.getBookId());
}
});
}
private void validateOrderInfo(OrderInfo orderInfo) throws NotValidOrderException {
if (orderInfo == null) {
throw new NotValidOrderException("Order cannot be null");
}
if (orderInfo.getOrderLines() == null || orderInfo.getOrderLines().isEmpty()) {
throw new OrderQuantityException("Order must contain at least one book");
}
if (orderInfo.getAddress() == null) {
throw new NotValidOrderException("Shipping address is required");
}
}
private double calculateTotalPriceToPay(OrderInfo orderInfo, Map<String, fr.iut_fbleau.but3.dev62.mylibrary.book.entity.Book> books) {
// Apply any potential discounts here
return calculateTotalPrice(orderInfo, books);
}
private UUID parseCustomerId(String customerId) throws CustomerNotFoundException {
if (customerId == null || customerId.trim().isEmpty()) {
throw new CustomerNotFoundException(null);
}
try {
return UUID.fromString(customerId);
} catch (IllegalArgumentException e) {
throw new CustomerNotFoundException(null);
}
}
private PaymentMethod parsePaymentMethod(String paymentMethod) {
try {
return PaymentMethod.valueOf(paymentMethod);
} catch (IllegalArgumentException | NullPointerException e) {
throw new InvalidPaymentMethodException("Payment method " + paymentMethod + " is not valid");
}
}
private UUID parseOrderId(String orderId) {
try {
return UUID.fromString(orderId);
} catch (IllegalArgumentException e) {
throw new OrderNotFoundException("Order with ID " + orderId + " was not found");
}
}
private double calculateTotalPrice(OrderInfo orderInfo, Map<String, fr.iut_fbleau.but3.dev62.mylibrary.book.entity.Book> books) {
return orderInfo.getOrderLines().stream()
.mapToDouble(line -> books.get(line.getBookId()).getPrice() * line.getQuantity())
.sum();
}
private void handleLoyaltyPointsPayment(Customer customer, double totalPrice) throws IllegalCustomerPointException {
int requiredPoints = (int) (totalPrice * 100);
if (customer.getLoyaltyPoints() < requiredPoints) {
throw new IllegalOrderPointException("Not enough loyalty points to pay for the order");
}
customer.removeLoyaltyPoints(requiredPoints);
customerRepository.save(customer);
}
}

View File

@@ -0,0 +1,66 @@
package fr.iut_fbleau.but3.dev62.mylibrary.order.validator;
import fr.iut_fbleau.but3.dev62.mylibrary.order.entity.Address;
import fr.iut_fbleau.but3.dev62.mylibrary.order.entity.Order;
import fr.iut_fbleau.but3.dev62.mylibrary.order.exception.NotValidOrderException;
public class OrderValidator {
public static void validate(Order order) {
if (order == null) {
throw new NotValidOrderException("Order cannot be null");
}
validatePrices(order);
validateAddress(order);
validatePaymentMethod(order);
validateOrderLines(order);
}
private static void validatePrices(Order order) {
if (order.getTotalPrice() <= 0) {
throw new NotValidOrderException("Total price must be positive");
}
if (order.getTotalPriceToPay() <= 0) {
throw new NotValidOrderException("Total price to pay must be positive");
}
if (order.getTotalPriceToPay() > order.getTotalPrice()) {
throw new NotValidOrderException("Total price to pay cannot exceed total price");
}
}
private static void validateOrderLines(Order order) {
if (order.getOrderLines() == null || order.getOrderLines().isEmpty()) {
throw new NotValidOrderException("Order must contain at least one line");
}
order.getOrderLines().forEach(line -> {
if (line.getQuantity() <= 0) {
throw new NotValidOrderException("Quantity must be positive");
}
});
}
private static void validateAddress(Order order) {
Address address = order.getShippingAddress();
if (address == null) {
throw new NotValidOrderException("Shipping address is required");
}
if (isNullOrBlank(address.getStreet()) ||
isNullOrBlank(address.getCity()) ||
isNullOrBlank(address.getPostalCode()) ||
isNullOrBlank(address.getCountry())) {
throw new NotValidOrderException("All address fields are required");
}
}
private static void validatePaymentMethod(Order order) {
if (order.getPaymentMethod() == null) {
throw new NotValidOrderException("Payment method cannot be null");
}
}
private static boolean isNullOrBlank(String value) {
return value == null || value.trim().isEmpty();
}
}

View File

@@ -0,0 +1,19 @@
package fr.iut_fbleau.but3.dev62.mylibrary.review;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import java.util.UUID;
@Builder
@Getter
@AllArgsConstructor
public class ReviewDto {
private final UUID reviewId;
private final long bookId;
private final String customerName;
private final String comment;
private final int rating;
}

View File

@@ -0,0 +1,16 @@
package fr.iut_fbleau.but3.dev62.mylibrary.review;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
@Builder
@Getter
@AllArgsConstructor
public class ReviewInfo {
private final String customerId;
private final long isbn;
private final int rating;
private final String comment;
}

View File

@@ -0,0 +1,29 @@
package fr.iut_fbleau.but3.dev62.mylibrary.review.converter;
import fr.iut_fbleau.but3.dev62.mylibrary.review.ReviewDto;
import fr.iut_fbleau.but3.dev62.mylibrary.review.ReviewInfo;
import fr.iut_fbleau.but3.dev62.mylibrary.review.entity.Review;
import java.util.UUID;
public class ReviewConverter {
public static ReviewDto toDto(Review review, UUID reviewId, String customerName) {
return ReviewDto.builder()
.reviewId(reviewId)
.bookId(review.getIsbn())
.customerName(customerName)
.comment(review.getComment())
.rating(review.getRating())
.build();
}
public static Review toDomain(ReviewInfo info) {
return Review.builder()
.customerId(UUID.fromString(info.getCustomerId()))
.isbn(info.getIsbn())
.rating(info.getRating())
.comment(info.getComment())
.build();
}
}

View File

@@ -0,0 +1,19 @@
package fr.iut_fbleau.but3.dev62.mylibrary.review.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.util.UUID;
@Builder
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class Review {
private UUID customerId;
private long isbn;
private int rating;
private String comment;
}

View File

@@ -0,0 +1,8 @@
package fr.iut_fbleau.but3.dev62.mylibrary.review.exception;
public class InvalidReviewRatingException extends RuntimeException {
public InvalidReviewRatingException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,8 @@
package fr.iut_fbleau.but3.dev62.mylibrary.review.exception;
public class ReviewAlreadyExistsException extends RuntimeException {
public ReviewAlreadyExistsException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,8 @@
package fr.iut_fbleau.but3.dev62.mylibrary.review.exception;
public class ReviewNotFoundException extends RuntimeException {
public ReviewNotFoundException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,44 @@
package fr.iut_fbleau.but3.dev62.mylibrary.review.repository;
import fr.iut_fbleau.but3.dev62.mylibrary.review.entity.Review;
import java.util.*;
import java.util.stream.Collectors;
public class ReviewRepository {
private final List<Review> reviews = new ArrayList<>();
public void save(Review review) {
reviews.add(review);
}
public List<Review> findAll() {
return new ArrayList<>(reviews);
}
public List<Review> findByIsbn(long isbn) {
return reviews.stream().filter(r -> r.getIsbn() == isbn).collect(Collectors.toList());
}
public List<Review> findByCustomerId(UUID customerId) {
return reviews.stream().filter(r -> r.getCustomerId().equals(customerId)).collect(Collectors.toList());
}
public boolean existsByCustomerIdAndIsbn(UUID customerId, long isbn) {
return reviews.stream().anyMatch(r -> r.getCustomerId().equals(customerId) && r.getIsbn() == isbn);
}
public void deleteByCustomerIdAndIsbn(UUID customerId, long isbn) {
reviews.removeIf(r -> r.getCustomerId().equals(customerId) && r.getIsbn() == isbn);
}
public void update(Review review) {
deleteByCustomerIdAndIsbn(review.getCustomerId(), review.getIsbn());
save(review);
}
public void deleteAll() {
reviews.clear();
}
}

View File

@@ -0,0 +1,71 @@
package fr.iut_fbleau.but3.dev62.mylibrary.review.usecase;
import fr.iut_fbleau.but3.dev62.mylibrary.book.repository.BookRepository;
import fr.iut_fbleau.but3.dev62.mylibrary.customer.repository.CustomerRepository;
import fr.iut_fbleau.but3.dev62.mylibrary.review.entity.Review;
import fr.iut_fbleau.but3.dev62.mylibrary.review.exception.InvalidReviewRatingException;
import fr.iut_fbleau.but3.dev62.mylibrary.review.exception.ReviewAlreadyExistsException;
import fr.iut_fbleau.but3.dev62.mylibrary.review.exception.ReviewNotFoundException;
import fr.iut_fbleau.but3.dev62.mylibrary.book.exception.BookNotFoundException;
import fr.iut_fbleau.but3.dev62.mylibrary.customer.exception.CustomerNotFoundException;
import fr.iut_fbleau.but3.dev62.mylibrary.review.repository.ReviewRepository;
import fr.iut_fbleau.but3.dev62.mylibrary.review.validator.ReviewValidator;
import java.util.List;
import java.util.UUID;
public class ReviewUseCase {
private final ReviewRepository reviewRepository;
private final BookRepository bookRepository;
private final CustomerRepository customerRepository;
public ReviewUseCase(ReviewRepository reviewRepository, BookRepository bookRepository, CustomerRepository customerRepository) {
this.reviewRepository = reviewRepository;
this.bookRepository = bookRepository;
this.customerRepository = customerRepository;
}
public void deleteReview(long isbn, UUID customerId) {
if (!reviewRepository.existsByCustomerIdAndIsbn(customerId, isbn)) {
throw new ReviewNotFoundException("No review found for the given customer and book.");
}
reviewRepository.deleteByCustomerIdAndIsbn(customerId, isbn);
}
public void submitReview(Review review) throws CustomerNotFoundException {
ReviewValidator.validate(review);
if (!bookRepository.existsByIsbn(String.valueOf(review.getIsbn()))) {
throw new BookNotFoundException("The book with ISBN " + review.getIsbn() + " was not found.");
}
if (!customerRepository.existsById(review.getCustomerId())) {
throw new CustomerNotFoundException(review.getCustomerId());
}
if (reviewRepository.existsByCustomerIdAndIsbn(review.getCustomerId(), review.getIsbn())) {
throw new ReviewAlreadyExistsException("A review already exists for this customer and book.");
}
reviewRepository.save(review);
}
public List<Review> getReviewsByCustomer(UUID customerId) {
return reviewRepository.findByCustomerId(customerId);
}
public void updateReview(Review review) {
ReviewValidator.validate(review);
if (!reviewRepository.existsByCustomerIdAndIsbn(review.getCustomerId(), review.getIsbn())) {
throw new ReviewNotFoundException("Cannot update: no existing review found for this customer and book.");
}
reviewRepository.update(review);
}
public List<Review> getReviewsByBook(long isbn) {
return reviewRepository.findByIsbn(isbn);
}
}

View File

@@ -0,0 +1,30 @@
package fr.iut_fbleau.but3.dev62.mylibrary.review.validator;
import fr.iut_fbleau.but3.dev62.mylibrary.review.entity.Review;
import fr.iut_fbleau.but3.dev62.mylibrary.review.exception.InvalidReviewRatingException;
public class ReviewValidator {
public static void validate(Review review) {
if (review == null) {
throw new IllegalArgumentException("The review provided is null.");
}
if (review.getCustomerId() == null) {
throw new IllegalArgumentException("Customer ID is required.");
}
if (review.getIsbn() <= 0) {
throw new IllegalArgumentException("ISBN must be a positive number.");
}
if (review.getComment() == null || review.getComment().trim().isEmpty()) {
throw new IllegalArgumentException("A review must contain a comment.");
}
int rating = review.getRating();
if (rating < 1 || rating > 5) {
throw new InvalidReviewRatingException("Rating must be within the range of 1 to 5.");
}
}
}

View File

@@ -0,0 +1,15 @@
package fr.iut_fbleau.but3.dev62.mylibrary.subscription;
import lombok.Builder;
import lombok.Getter;
import java.util.UUID;
@Builder
@Getter
public class SubscriptionDTO {
private final UUID id;
private final UUID customerId;
private final Integer duration;
private final String paymentMethod;
private final String debutDate;
}

View File

@@ -0,0 +1,7 @@
package fr.iut_fbleau.but3.dev62.mylibrary.subscription;
import java.util.UUID;
public record SubscriptionInfo(UUID customerId, Integer duration, String paymentMethod) {
}

View File

@@ -0,0 +1,31 @@
package fr.iut_fbleau.but3.dev62.mylibrary.subscription.converter;
import fr.iut_fbleau.but3.dev62.mylibrary.subscription.SubscriptionDTO;
import fr.iut_fbleau.but3.dev62.mylibrary.subscription.SubscriptionInfo;
import fr.iut_fbleau.but3.dev62.mylibrary.subscription.entity.Subscription;
public final class SubscriptionConverter {
private SubscriptionConverter() {
}
public static Subscription toDomain(SubscriptionInfo newSubscription) {
return Subscription.builder()
.customerId(newSubscription.customerId())
.duration(newSubscription.duration())
.paymentMethod(newSubscription.paymentMethod())
.build();
}
public static SubscriptionDTO toDTO(Subscription subscription) {
return SubscriptionDTO.builder()
.id(subscription.getId())
.customerId(subscription.getCustomerId())
.duration(subscription.getDuration())
.paymentMethod(subscription.getPaymentMethod())
.debutDate(subscription.getDebutDate())
.build();
}
}

View File

@@ -0,0 +1,24 @@
package fr.iut_fbleau.but3.dev62.mylibrary.subscription.entity;
import java.util.UUID;
import lombok.Builder;
import lombok.Getter;
import java.time.LocalDate;
@Builder
@Getter
public class Subscription {
private UUID id;
private UUID customerId;
private Integer duration;
private String paymentMethod;
private String debutDate;
public void setRandomUUID() {
this.id = UUID.randomUUID();
}
public void setDebutDate(String debutDate) {
this.debutDate = LocalDate.now().toString();
}
}

View File

@@ -0,0 +1,8 @@
package fr.iut_fbleau.but3.dev62.mylibrary.subscription.exception;
public class NotValidSubscriptionException extends Exception {
public NotValidSubscriptionException(String message) {
super(message);
}
}

Some files were not shown because too many files have changed in this diff Show More