diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/config/SecurityConfig.java b/src/main/java/_11/asktpk/artisanconnectbackend/config/SecurityConfig.java index bf88946..ca98ca2 100644 --- a/src/main/java/_11/asktpk/artisanconnectbackend/config/SecurityConfig.java +++ b/src/main/java/_11/asktpk/artisanconnectbackend/config/SecurityConfig.java @@ -26,7 +26,7 @@ public class SecurityConfig { .cors(cors -> cors.configure(http)) .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests(auth -> auth - .requestMatchers("/api/v1/auth/**").permitAll() + .requestMatchers("/api/v1/auth/**", "/api/v1/payments/notification").permitAll() .anyRequest().authenticated()) .sessionManagement(session -> session .sessionCreationPolicy(SessionCreationPolicy.STATELESS)); diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/controller/NoticeController.java b/src/main/java/_11/asktpk/artisanconnectbackend/controller/NoticeController.java index 63bea89..d2c8cfc 100644 --- a/src/main/java/_11/asktpk/artisanconnectbackend/controller/NoticeController.java +++ b/src/main/java/_11/asktpk/artisanconnectbackend/controller/NoticeController.java @@ -1,17 +1,17 @@ package _11.asktpk.artisanconnectbackend.controller; -import _11.asktpk.artisanconnectbackend.dto.NoticeAdditionDTO; -import _11.asktpk.artisanconnectbackend.dto.NoticeBoostDTO; -import _11.asktpk.artisanconnectbackend.dto.RequestResponseDTO; +import _11.asktpk.artisanconnectbackend.dto.*; import _11.asktpk.artisanconnectbackend.service.ClientService; import _11.asktpk.artisanconnectbackend.service.NoticeService; -import _11.asktpk.artisanconnectbackend.dto.NoticeDTO; +import _11.asktpk.artisanconnectbackend.utils.Enums; +import _11.asktpk.artisanconnectbackend.utils.Tools; import jakarta.persistence.EntityNotFoundException; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import java.util.ArrayList; +import java.util.Arrays; import java.util.List; @RequestMapping("/api/v1/notices") @@ -19,14 +19,16 @@ import java.util.List; public class NoticeController { private final NoticeService noticeService; private final ClientService clientService; + private final Tools tools; - public NoticeController(NoticeService noticeService, ClientService clientService) { + public NoticeController(NoticeService noticeService, ClientService clientService, Tools tools) { this.noticeService = noticeService; this.clientService = clientService; + this.tools = tools; } @GetMapping("/get/all") - public List getAllNotices() { + public List getAllNotices() { return noticeService.getAllNotices(); } @@ -40,57 +42,34 @@ public class NoticeController { } @PostMapping("/add") - public ResponseEntity addNotice(@RequestBody NoticeDTO dto) { - if (!clientService.clientExists(dto.getClientId())) { + public ResponseEntity addNotice(@RequestBody NoticeRequestDTO dto, HttpServletRequest request) { + Long clientId = tools.getClientIdFromRequest(request); + if (!clientService.clientExists(clientId)) { return ResponseEntity .status(HttpStatus.BAD_REQUEST) - .body(new NoticeAdditionDTO("Nie znaleziono klienta o ID: " + dto.getClientId())); + .body(new NoticeAdditionDTO("Nie znaleziono klienta o ID: " + clientId)); } - if (dto.getCategory() == null) { + dto.setClientId(clientId); + + if (dto.getCategory() == null || !Arrays.asList(Enums.Category.values()).contains(dto.getCategory())) { return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new NoticeAdditionDTO("Nie ma takiej kategorii")); } - dto.setPublishDate(java.time.LocalDateTime.now()); Long newNoticeId = noticeService.addNotice(dto); return ResponseEntity.status(HttpStatus.CREATED).body(new NoticeAdditionDTO(newNoticeId ,"Dodano ogłoszenie.")); } - // TODO: zamiast dodawać tutaj pętlą, musi to robić NoticeService, trzeba zaimplementować odpowienią metodę - @PostMapping("/bulk_add") - public ResponseEntity addNotices(@RequestBody List notices_list) { - ResponseEntity response = new ResponseEntity<>(HttpStatus.CREATED); - List errors = new ArrayList<>(); - boolean isError = false; - - if (notices_list.isEmpty()) { - return response.status(HttpStatus.BAD_REQUEST).body("Lista ogłoszeń jest pusta."); - } - - for (NoticeDTO dto : notices_list) { - if (!clientService.clientExists(dto.getClientId())) { - isError = true; - errors.add(dto.getClientId().toString()); - } else { - if (!isError) { - noticeService.addNotice(dto); - } - } - } - - if (isError) { - return response.status(HttpStatus.BAD_REQUEST).body("Nie znaleziono klientów: " + errors); - } - - return response; - } - @PutMapping("/edit/{id}") - public ResponseEntity editNotice(@PathVariable("id") long id, @RequestBody NoticeDTO dto) { + public ResponseEntity editNotice(@PathVariable("id") long id, @RequestBody NoticeRequestDTO dto, HttpServletRequest request) { + Long clientIdFromToken = tools.getClientIdFromRequest(request); if (noticeService.noticeExists(id)) { + if (!noticeService.isNoticeOwnedByClient(id, clientIdFromToken)) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new RequestResponseDTO("Nie masz uprawnień do edycji tego ogłoszenia.")); + } try { - return new ResponseEntity<>(noticeService.updateNotice(id, dto), HttpStatus.OK); + return ResponseEntity.status(HttpStatus.OK).body(noticeService.updateNotice(id, dto)); } catch (EntityNotFoundException e) { return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage()); } @@ -100,8 +79,13 @@ public class NoticeController { } @DeleteMapping("/delete/{id}") - public ResponseEntity deleteNotice(@PathVariable("id") long id) { + public ResponseEntity deleteNotice(@PathVariable("id") long id, HttpServletRequest request) { + Long clientIdFromToken = tools.getClientIdFromRequest(request); if (noticeService.noticeExists(id)) { + if (!noticeService.isNoticeOwnedByClient(id, clientIdFromToken)) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new RequestResponseDTO("Nie masz uprawnień do usunięcia tego ogłoszenia.")); + } + noticeService.deleteNotice(id); return ResponseEntity.status(HttpStatus.OK).body(new RequestResponseDTO("Pomyślnie usunięto ogłoszenie o ID: " + id)); } else { @@ -109,9 +93,10 @@ public class NoticeController { } } - @PostMapping("/boost/{id}") - public ResponseEntity boostNotice(@PathVariable("id") long clientId, @RequestBody NoticeBoostDTO dto) { - if (!noticeService.isNoticeOwnedByClient(dto.getNoticeId(), clientId)) { + @PostMapping("/boost") + public ResponseEntity boostNotice(@RequestBody NoticeBoostDTO dto, HttpServletRequest request) { + Long clientId = tools.getClientIdFromRequest(request); + if (noticeService.isNoticeOwnedByClient(dto.getNoticeId(), clientId)) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new RequestResponseDTO("Ogłoszenie nie istnieje lub nie należy do zalogowanego klienta.")); } noticeService.boostNotice(dto.getNoticeId()); diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/controller/OrderController.java b/src/main/java/_11/asktpk/artisanconnectbackend/controller/OrderController.java index 6571d3b..71cb942 100644 --- a/src/main/java/_11/asktpk/artisanconnectbackend/controller/OrderController.java +++ b/src/main/java/_11/asktpk/artisanconnectbackend/controller/OrderController.java @@ -1,53 +1,129 @@ package _11.asktpk.artisanconnectbackend.controller; import _11.asktpk.artisanconnectbackend.dto.*; +import _11.asktpk.artisanconnectbackend.entities.Client; import _11.asktpk.artisanconnectbackend.entities.Order; -import _11.asktpk.artisanconnectbackend.service.ClientService; +import _11.asktpk.artisanconnectbackend.entities.Payment; import _11.asktpk.artisanconnectbackend.service.OrderService; import _11.asktpk.artisanconnectbackend.service.PaymentService; import _11.asktpk.artisanconnectbackend.utils.Enums; +import _11.asktpk.artisanconnectbackend.utils.Tools; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import java.util.List; + + @RestController @RequestMapping("/api/v1/orders") public class OrderController { private final OrderService orderService; private final PaymentService paymentService; + private final Tools tools; - public OrderController(OrderService orderService, PaymentService paymentService) { + public OrderController(OrderService orderService, PaymentService paymentService, Tools tools) { this.orderService = orderService; this.paymentService = paymentService; + this.tools = tools; } @PostMapping("/add") - public ResponseEntity addClient(@RequestBody OrderDTO orderDTO) { - return new ResponseEntity<>(orderService.addOrder(orderDTO), HttpStatus.CREATED); + public ResponseEntity addClient(@RequestBody OrderDTO orderDTO, HttpServletRequest request) { + orderDTO.setClientId(tools.getClientIdFromRequest(request)); + return ResponseEntity.status(HttpStatus.CREATED).body(orderService.addOrder(orderDTO)); } @PutMapping("/changeStatus") - public ResponseEntity changeStatus(@RequestBody OrderStatusDTO orderStatusDTO) { - return new ResponseEntity<>(orderService.changeOrderStatus(orderStatusDTO.getId(),orderStatusDTO.getStatus()), HttpStatus.OK); + public ResponseEntity changeStatus(@RequestBody OrderStatusDTO orderStatusDTO) { + return ResponseEntity.status(HttpStatus.OK).body(orderService.changeOrderStatus(orderStatusDTO.getId(), orderStatusDTO.getStatus())); } @PostMapping("/token") - public ResponseEntity fetchToken() { - Order order = orderService.getOrderById(1L); - OAuthPaymentResponseDTO authPaymentDTO= paymentService.getOAuthToken(); + public ResponseEntity fetchToken(HttpServletRequest request,@RequestParam Long orderId) { + Order order = orderService.getOrderById(orderId); + Client client = order.getClient(); + OAuthPaymentResponseDTO authPaymentDTO = paymentService.getOAuthToken(); TransactionPaymentRequestDTO.Payer payer = new TransactionPaymentRequestDTO.Payer( - "patryk@test.pl", "Patryk Test"); + client.getEmail(), client.getFirstName()+' '+client.getLastName()); String paymentDescription = order.getOrderType() == Enums.OrderType.ACTIVATION ? "Aktywacja ogłoszenia" : "Podbicie ogłoszenia"; paymentDescription += order.getNotice().getTitle(); - TransactionPaymentRequestDTO request = new TransactionPaymentRequestDTO( + TransactionPaymentRequestDTO paymentRequest = new TransactionPaymentRequestDTO( order.getAmount(), paymentDescription, payer); - String response = paymentService.createTransaction(order,authPaymentDTO.getAccess_token(), request); - System.out.println(response); - System.out.println(request); + String response = paymentService.createTransaction(order, authPaymentDTO.getAccess_token(), paymentRequest); - return ResponseEntity.ok(response); + return ResponseEntity.status(HttpStatus.OK).body(response); } + + @GetMapping("/get/all") + public ResponseEntity> getOrders(HttpServletRequest request) { + Long clientId = tools.getClientIdFromRequest(request); + List orders = orderService.getOrdersByClientId(clientId); + + List dtoList = orders.stream().map(order -> { + OrderWithPaymentsDTO dto = new OrderWithPaymentsDTO(); + dto.setOrderId(order.getId()); + dto.setOrderType(order.getOrderType().name()); + dto.setStatus(order.getStatus().name()); + dto.setAmount(order.getAmount()); + dto.setCreatedAt(order.getCreatedAt()); + + List payments = paymentService.getPaymentsByOrderId(order.getId()); + + List paymentDTOs = payments.stream().map(payment -> { + PaymentDTO pDto = new PaymentDTO(); + pDto.setPaymentId(payment.getIdPayment()); + pDto.setAmount(payment.getAmount()); + pDto.setStatus(payment.getStatus().name()); + pDto.setTransactionPaymentUrl(payment.getTransactionPaymentUrl()); + pDto.setTransactionId(payment.getTransactionId()); + return pDto; + }).toList(); + + dto.setPayments(paymentDTOs); + return dto; + }).toList(); + + return ResponseEntity.ok(dtoList); + } + + @GetMapping("/get/{orderId}") + public ResponseEntity getOrderById(HttpServletRequest request, + @PathVariable Long orderId) { + Long clientId = tools.getClientIdFromRequest(request); + + Order order = orderService.getOrderById(orderId); + + if (!order.getClient().getId().equals(clientId)) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); + } + + OrderWithPaymentsDTO dto = new OrderWithPaymentsDTO(); + dto.setOrderId(order.getId()); + dto.setOrderType(order.getOrderType().name()); + dto.setStatus(order.getStatus().name()); + dto.setAmount(order.getAmount()); + dto.setCreatedAt(order.getCreatedAt()); + + List payments = paymentService.getPaymentsByOrderId(order.getId()); + List paymentDTOs = payments.stream().map(payment -> { + PaymentDTO pDto = new PaymentDTO(); + pDto.setPaymentId(payment.getIdPayment()); + pDto.setAmount(payment.getAmount()); + pDto.setStatus(payment.getStatus().name()); + pDto.setTransactionPaymentUrl(payment.getTransactionPaymentUrl()); + pDto.setTransactionId(payment.getTransactionId()); + return pDto; + }).toList(); + + dto.setPayments(paymentDTOs); + + return ResponseEntity.ok(dto); + } + + } diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/controller/PaymentController.java b/src/main/java/_11/asktpk/artisanconnectbackend/controller/PaymentController.java index 8449e5c..7fc105d 100644 --- a/src/main/java/_11/asktpk/artisanconnectbackend/controller/PaymentController.java +++ b/src/main/java/_11/asktpk/artisanconnectbackend/controller/PaymentController.java @@ -39,9 +39,6 @@ public class PaymentController { @PostMapping(value = "/notification", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) public ResponseEntity handleTpayNotification(@RequestParam Map params) { - log.info("=== ODEBRANO NOTYFIKACJĘ Tpay ==="); - log.info("Parametry:\n{}", paramsToLogString(params)); - String id = params.get("id"); String trId = params.get("tr_id"); String trAmount = params.get("tr_amount"); @@ -54,7 +51,6 @@ public class PaymentController { ); if (!expectedMd5.equals(md5sum)) { - log.warn("❌ Błędna suma kontrolna! Otrzymano: {}, Oczekiwano: {}", md5sum, expectedMd5); return ResponseEntity.status(400).body("INVALID CHECKSUM"); } @@ -63,7 +59,6 @@ public class PaymentController { Payment payment = optionalPayment.get(); if ("true".equalsIgnoreCase(trStatus) || "PAID".equalsIgnoreCase(trStatus)) { - log.info("✅ Transakcja opłacona: tr_id={}, kwota={}", trId, params.get("tr_paid")); payment.setStatus(Enums.PaymentStatus.CORRECT); if (payment.getOrder() != null) { @@ -78,7 +73,6 @@ public class PaymentController { } } else if ("false".equalsIgnoreCase(trStatus)) { - log.warn("❌ Transakcja nieudana: {}", trId); payment.setStatus(Enums.PaymentStatus.INCORRECT); if (payment.getOrder() != null) { @@ -87,10 +81,7 @@ public class PaymentController { } paymentRepository.save(payment); - } else { - log.warn("⚠️ Brak płatności o tr_id={}", trId); } - return ResponseEntity.ok("TRUE"); } diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/controller/WishlistController.java b/src/main/java/_11/asktpk/artisanconnectbackend/controller/WishlistController.java index 5e95337..e5e45fd 100644 --- a/src/main/java/_11/asktpk/artisanconnectbackend/controller/WishlistController.java +++ b/src/main/java/_11/asktpk/artisanconnectbackend/controller/WishlistController.java @@ -1,35 +1,39 @@ package _11.asktpk.artisanconnectbackend.controller; -import _11.asktpk.artisanconnectbackend.dto.NoticeDTO; +import _11.asktpk.artisanconnectbackend.dto.NoticeResponseDTO; import _11.asktpk.artisanconnectbackend.dto.RequestResponseDTO; -import _11.asktpk.artisanconnectbackend.dto.WishlistDTO; import _11.asktpk.artisanconnectbackend.service.ClientService; import _11.asktpk.artisanconnectbackend.service.NoticeService; import _11.asktpk.artisanconnectbackend.service.WishlistService; +import _11.asktpk.artisanconnectbackend.utils.Tools; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.List; +@Slf4j @RestController @RequestMapping("/api/v1/wishlist") public class WishlistController { private final WishlistService wishlistService; private final ClientService clientService; private final NoticeService noticeService; + private final Tools tools; - public WishlistController(WishlistService wishlistService, ClientService clientService, NoticeService noticeService) { + public WishlistController(WishlistService wishlistService, ClientService clientService, NoticeService noticeService, Tools tools) { this.wishlistService = wishlistService; this.clientService = clientService; this.noticeService = noticeService; + this.tools = tools; } @PostMapping("/toggle/{noticeId}") - public ResponseEntity toggleWishlist(@PathVariable Long noticeId) { - - Long clientId = 1L; - NoticeDTO noticeDTO = noticeService.getNoticeById(noticeId); - if (noticeDTO == null) { + public ResponseEntity toggleWishlist(@PathVariable Long noticeId, HttpServletRequest request) { + Long clientId = tools.getClientIdFromRequest(request); + NoticeResponseDTO noticeResponseDTO = noticeService.getNoticeById(noticeId); + if (noticeResponseDTO == null) { return ResponseEntity.badRequest().body(new RequestResponseDTO("Notice not found")); } boolean added = wishlistService.toggleWishlist( @@ -51,9 +55,8 @@ public class WishlistController { // } @GetMapping("/") - public List getWishlistForClient() { - // TODO: Replace with actual client ID from authentication context - Long clientId = 1L; + public List getWishlistForClient(HttpServletRequest request) { + Long clientId = tools.getClientIdFromRequest(request); return wishlistService.getNoticesInWishlist(clientId); } } \ No newline at end of file diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/dto/AttributeDto.java b/src/main/java/_11/asktpk/artisanconnectbackend/dto/AttributeDto.java new file mode 100644 index 0000000..dbc69d6 --- /dev/null +++ b/src/main/java/_11/asktpk/artisanconnectbackend/dto/AttributeDto.java @@ -0,0 +1,11 @@ +package _11.asktpk.artisanconnectbackend.dto; + + +import lombok.Getter; +import lombok.Setter; + +@Getter @Setter +public class AttributeDto { + private String name; + private String value; +} diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/dto/NoticeRequestDTO.java b/src/main/java/_11/asktpk/artisanconnectbackend/dto/NoticeRequestDTO.java new file mode 100644 index 0000000..f81e423 --- /dev/null +++ b/src/main/java/_11/asktpk/artisanconnectbackend/dto/NoticeRequestDTO.java @@ -0,0 +1,27 @@ +package _11.asktpk.artisanconnectbackend.dto; + +import _11.asktpk.artisanconnectbackend.utils.Enums; +import lombok.Getter; +import lombok.Setter; +import java.util.List; + +@Getter @Setter +public class NoticeRequestDTO { + private String title; + + private Long clientId; + + private String description; + + private Double price; + + private Enums.Category category; + + private Enums.Status status; + + private List attributes; + + public NoticeRequestDTO() { + + } +} diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/dto/NoticeDTO.java b/src/main/java/_11/asktpk/artisanconnectbackend/dto/NoticeResponseDTO.java similarity index 70% rename from src/main/java/_11/asktpk/artisanconnectbackend/dto/NoticeDTO.java rename to src/main/java/_11/asktpk/artisanconnectbackend/dto/NoticeResponseDTO.java index 80259db..327cfbd 100644 --- a/src/main/java/_11/asktpk/artisanconnectbackend/dto/NoticeDTO.java +++ b/src/main/java/_11/asktpk/artisanconnectbackend/dto/NoticeResponseDTO.java @@ -1,6 +1,5 @@ package _11.asktpk.artisanconnectbackend.dto; -import _11.asktpk.artisanconnectbackend.entities.AttributesNotice; import _11.asktpk.artisanconnectbackend.utils.Enums; import lombok.Getter; import lombok.Setter; @@ -9,7 +8,7 @@ import java.time.LocalDateTime; import java.util.List; @Getter @Setter -public class NoticeDTO { +public class NoticeResponseDTO { private long noticeId; private String title; @@ -26,11 +25,9 @@ public class NoticeDTO { private LocalDateTime publishDate; - private List attributesNotices; + private List attributes; - private boolean isWishlisted; - - public NoticeDTO() { + public NoticeResponseDTO() { } } diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/dto/OrderWithPaymentsDTO.java b/src/main/java/_11/asktpk/artisanconnectbackend/dto/OrderWithPaymentsDTO.java new file mode 100644 index 0000000..5998910 --- /dev/null +++ b/src/main/java/_11/asktpk/artisanconnectbackend/dto/OrderWithPaymentsDTO.java @@ -0,0 +1,62 @@ +package _11.asktpk.artisanconnectbackend.dto; + +import java.time.LocalDateTime; +import java.util.List; + +public class OrderWithPaymentsDTO { + private Long orderId; + private String orderType; + private String status; + private Double amount; + private LocalDateTime createdAt; + private List payments; + + // Gettery i settery + public Long getOrderId() { + return orderId; + } + + public void setOrderId(Long orderId) { + this.orderId = orderId; + } + + public String getOrderType() { + return orderType; + } + + public void setOrderType(String orderType) { + this.orderType = orderType; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public Double getAmount() { + return amount; + } + + public void setAmount(Double amount) { + this.amount = amount; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } + + public List getPayments() { + return payments; + } + + public void setPayments(List payments) { + this.payments = payments; + } +} diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/dto/PaymentDTO.java b/src/main/java/_11/asktpk/artisanconnectbackend/dto/PaymentDTO.java new file mode 100644 index 0000000..40b378e --- /dev/null +++ b/src/main/java/_11/asktpk/artisanconnectbackend/dto/PaymentDTO.java @@ -0,0 +1,34 @@ +package _11.asktpk.artisanconnectbackend.dto; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class PaymentDTO { + private Long paymentId; + private Double amount; + private String status; + private String transactionPaymentUrl; + private String transactionId; + + public void setPaymentId(Long paymentId) { + this.paymentId = paymentId; + } + + public void setAmount(Double amount) { + this.amount = amount; + } + + public void setStatus(String status) { + this.status = status; + } + + public void setTransactionPaymentUrl(String transactionPaymentUrl) { + this.transactionPaymentUrl = transactionPaymentUrl; + } + + public void setTransactionId(String transactionId) { + this.transactionId = transactionId; + } +} diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/entities/AttributeValues.java b/src/main/java/_11/asktpk/artisanconnectbackend/entities/AttributeValues.java index 0625d3b..90570ee 100644 --- a/src/main/java/_11/asktpk/artisanconnectbackend/entities/AttributeValues.java +++ b/src/main/java/_11/asktpk/artisanconnectbackend/entities/AttributeValues.java @@ -1,9 +1,12 @@ package _11.asktpk.artisanconnectbackend.entities; import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; @Entity @Table(name = "attribute_values") +@Getter @Setter public class AttributeValues { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -14,6 +17,4 @@ public class AttributeValues { private Attributes attribute; private String value; - - // Getters, setters, and constructors } diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/entities/Attributes.java b/src/main/java/_11/asktpk/artisanconnectbackend/entities/Attributes.java index ae405fa..a6b4c52 100644 --- a/src/main/java/_11/asktpk/artisanconnectbackend/entities/Attributes.java +++ b/src/main/java/_11/asktpk/artisanconnectbackend/entities/Attributes.java @@ -1,10 +1,14 @@ package _11.asktpk.artisanconnectbackend.entities; import jakarta.persistence.*; +import lombok.Setter; +import lombok.Getter; + import java.util.List; @Entity @Table(name = "attributes") +@Getter @Setter public class Attributes { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -12,8 +16,6 @@ public class Attributes { private String name; - @OneToMany(mappedBy = "attribute", cascade = CascadeType.ALL) + @OneToMany(mappedBy = "attribute") private List attributeValues; - - // Getters, setters, and constructors } diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/entities/AttributesNotice.java b/src/main/java/_11/asktpk/artisanconnectbackend/entities/AttributesNotice.java index 66ef0d0..2558721 100644 --- a/src/main/java/_11/asktpk/artisanconnectbackend/entities/AttributesNotice.java +++ b/src/main/java/_11/asktpk/artisanconnectbackend/entities/AttributesNotice.java @@ -1,21 +1,20 @@ package _11.asktpk.artisanconnectbackend.entities; import jakarta.persistence.*; +import lombok.Setter; +import lombok.Getter; @Entity @Table(name = "attributes_notice") +@Getter @Setter public class AttributesNotice { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne - @JoinColumn(name = "id_notice") - private Notice notice; + private Long notice_id; @ManyToOne @JoinColumn(name = "id_value") private AttributeValues attributeValue; - - // Getters, setters, and constructors } \ No newline at end of file diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/entities/Notice.java b/src/main/java/_11/asktpk/artisanconnectbackend/entities/Notice.java index 2d6bb56..80d5587 100644 --- a/src/main/java/_11/asktpk/artisanconnectbackend/entities/Notice.java +++ b/src/main/java/_11/asktpk/artisanconnectbackend/entities/Notice.java @@ -35,10 +35,10 @@ public class Notice { private LocalDateTime publishDate; - @OneToMany(mappedBy = "notice", cascade = CascadeType.ALL) + @OneToMany(mappedBy = "notice_id") private List attributesNotices; - @OneToMany(mappedBy = "notice", cascade = CascadeType.ALL) + @OneToMany(mappedBy = "notice") private List orders; // @OneToMany(mappedBy = "notice", cascade = CascadeType.ALL) diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/repository/AttributeValuesRepository.java b/src/main/java/_11/asktpk/artisanconnectbackend/repository/AttributeValuesRepository.java new file mode 100644 index 0000000..8e7f330 --- /dev/null +++ b/src/main/java/_11/asktpk/artisanconnectbackend/repository/AttributeValuesRepository.java @@ -0,0 +1,14 @@ +package _11.asktpk.artisanconnectbackend.repository; + +import _11.asktpk.artisanconnectbackend.entities.AttributeValues; +import _11.asktpk.artisanconnectbackend.entities.Attributes; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface AttributeValuesRepository extends JpaRepository { + + Optional findByAttributeAndValue(Attributes attribute, String value); +} diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/repository/AttributesNoticeRepository.java b/src/main/java/_11/asktpk/artisanconnectbackend/repository/AttributesNoticeRepository.java new file mode 100644 index 0000000..2c9a93d --- /dev/null +++ b/src/main/java/_11/asktpk/artisanconnectbackend/repository/AttributesNoticeRepository.java @@ -0,0 +1,9 @@ +package _11.asktpk.artisanconnectbackend.repository; + +import _11.asktpk.artisanconnectbackend.entities.AttributesNotice; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface AttributesNoticeRepository extends JpaRepository { +} diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/repository/AttributesRepository.java b/src/main/java/_11/asktpk/artisanconnectbackend/repository/AttributesRepository.java new file mode 100644 index 0000000..2a8bd0e --- /dev/null +++ b/src/main/java/_11/asktpk/artisanconnectbackend/repository/AttributesRepository.java @@ -0,0 +1,12 @@ +package _11.asktpk.artisanconnectbackend.repository; + +import _11.asktpk.artisanconnectbackend.entities.Attributes; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface AttributesRepository extends JpaRepository { + Optional findByName(String name); +} diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/repository/NoticeRepository.java b/src/main/java/_11/asktpk/artisanconnectbackend/repository/NoticeRepository.java index d2b3387..7de86c2 100644 --- a/src/main/java/_11/asktpk/artisanconnectbackend/repository/NoticeRepository.java +++ b/src/main/java/_11/asktpk/artisanconnectbackend/repository/NoticeRepository.java @@ -1,11 +1,9 @@ package _11.asktpk.artisanconnectbackend.repository; import _11.asktpk.artisanconnectbackend.entities.Notice; - import org.springframework.data.jpa.repository.JpaRepository; public interface NoticeRepository extends JpaRepository { boolean existsByIdNoticeAndClientId(long noticeId, long clientId); - -} +} \ No newline at end of file diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/repository/OrderRepository.java b/src/main/java/_11/asktpk/artisanconnectbackend/repository/OrderRepository.java index 422ab2d..6565b0a 100644 --- a/src/main/java/_11/asktpk/artisanconnectbackend/repository/OrderRepository.java +++ b/src/main/java/_11/asktpk/artisanconnectbackend/repository/OrderRepository.java @@ -4,8 +4,10 @@ import _11.asktpk.artisanconnectbackend.entities.Order; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository public interface OrderRepository extends JpaRepository { - + List findByClientId(Long clientId); } diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/repository/PaymentRepository.java b/src/main/java/_11/asktpk/artisanconnectbackend/repository/PaymentRepository.java index 486d80d..8aaedf9 100644 --- a/src/main/java/_11/asktpk/artisanconnectbackend/repository/PaymentRepository.java +++ b/src/main/java/_11/asktpk/artisanconnectbackend/repository/PaymentRepository.java @@ -4,9 +4,12 @@ import _11.asktpk.artisanconnectbackend.entities.Payment; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.List; import java.util.Optional; @Repository public interface PaymentRepository extends JpaRepository { Optional findByTransactionId(String transactionId); + + List findAllByOrderId(Long id); } diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/security/JwtRequestFilter.java b/src/main/java/_11/asktpk/artisanconnectbackend/security/JwtRequestFilter.java index 035d373..ff66518 100644 --- a/src/main/java/_11/asktpk/artisanconnectbackend/security/JwtRequestFilter.java +++ b/src/main/java/_11/asktpk/artisanconnectbackend/security/JwtRequestFilter.java @@ -43,7 +43,7 @@ public class JwtRequestFilter extends OncePerRequestFilter { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); - String jsonResponse = "{\"error\": \"Token is invalid or expired. Please login again.\"}"; + String jsonResponse = "{\"error\": \"Token is invalid. Please login again.\"}"; response.getWriter().write(jsonResponse); return; } @@ -53,6 +53,7 @@ public class JwtRequestFilter extends OncePerRequestFilter { } catch (ExpiredJwtException expiredJwtException) { logger.error(expiredJwtException.getMessage()); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + response.getWriter().write(new RequestResponseDTO("Authentication token is expired. Please login again.").toJSON()); return; } catch (Exception e) { logger.error(e.getMessage()); diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/security/JwtUtil.java b/src/main/java/_11/asktpk/artisanconnectbackend/security/JwtUtil.java index ae36e06..27fee78 100644 --- a/src/main/java/_11/asktpk/artisanconnectbackend/security/JwtUtil.java +++ b/src/main/java/_11/asktpk/artisanconnectbackend/security/JwtUtil.java @@ -82,6 +82,10 @@ public class JwtUtil { return extractAllClaims(token).get("role", String.class); } + public Long extractUserId(String token) { + return extractAllClaims(token).get("userId", Long.class); + } + public T extractClaim(String token, Function claimsResolver) { final Claims claims = extractAllClaims(token); return claimsResolver.apply(claims); diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/service/NoticeService.java b/src/main/java/_11/asktpk/artisanconnectbackend/service/NoticeService.java index c5fd8be..28c3639 100644 --- a/src/main/java/_11/asktpk/artisanconnectbackend/service/NoticeService.java +++ b/src/main/java/_11/asktpk/artisanconnectbackend/service/NoticeService.java @@ -1,10 +1,10 @@ package _11.asktpk.artisanconnectbackend.service; -import _11.asktpk.artisanconnectbackend.entities.Client; -import _11.asktpk.artisanconnectbackend.entities.Notice; -import _11.asktpk.artisanconnectbackend.repository.ClientRepository; -import _11.asktpk.artisanconnectbackend.repository.NoticeRepository; -import _11.asktpk.artisanconnectbackend.dto.NoticeDTO; +import _11.asktpk.artisanconnectbackend.dto.AttributeDto; +import _11.asktpk.artisanconnectbackend.dto.NoticeRequestDTO; +import _11.asktpk.artisanconnectbackend.entities.*; +import _11.asktpk.artisanconnectbackend.repository.*; +import _11.asktpk.artisanconnectbackend.dto.NoticeResponseDTO; import jakarta.persistence.EntityNotFoundException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -14,7 +14,6 @@ import org.springframework.stereotype.Service; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; -import java.util.Optional; @Service public class NoticeService { @@ -25,25 +24,32 @@ public class NoticeService { private final NoticeRepository noticeRepository; private final ClientRepository clientRepository; - private final WishlistService wishlistService; private final ImageService imageService; + private final AttributesRepository attributesRepository; + private final AttributeValuesRepository attributeValuesRepository; + private final AttributesNoticeRepository attributesNoticeRepository; - public NoticeService(NoticeRepository noticeRepository, ClientRepository clientRepository, WishlistService wishlistService, ImageService imageService) { + public NoticeService(NoticeRepository noticeRepository, + ClientRepository clientRepository, + ImageService imageService, + AttributesRepository attributesRepository, + AttributeValuesRepository attributeValuesRepository, + AttributesNoticeRepository attributesNoticeRepository) { this.noticeRepository = noticeRepository; this.clientRepository = clientRepository; - this.wishlistService = wishlistService; this.imageService = imageService; + this.attributesRepository = attributesRepository; + this.attributeValuesRepository = attributeValuesRepository; + this.attributesNoticeRepository = attributesNoticeRepository; } - public Notice fromDTO(NoticeDTO dto) { + public Notice fromDTO(NoticeRequestDTO dto) { Notice notice = new Notice(); notice.setTitle(dto.getTitle()); notice.setDescription(dto.getDescription()); notice.setPrice(dto.getPrice()); notice.setCategory(dto.getCategory()); notice.setStatus(dto.getStatus()); - notice.setPublishDate(dto.getPublishDate()); - notice.setAttributesNotices(dto.getAttributesNotices()); Client client = clientRepository.findById(dto.getClientId()) .orElseThrow(() -> new EntityNotFoundException("Nie znaleziono klienta o ID: " + dto.getClientId())); @@ -52,15 +58,8 @@ public class NoticeService { return notice; } - private NoticeDTO toDTO(Notice notice) { - NoticeDTO dto = new NoticeDTO(); - // TODO: To be updated using AuthService after implementing authentication. - Optional client = clientRepository.findById(1L); - boolean isWishlisted = false; - if (client.isPresent()) { - Client c = client.get(); - isWishlisted = wishlistService.isWishlisted(c, notice); - } + private NoticeResponseDTO toDTO(Notice notice) { + NoticeResponseDTO dto = new NoticeResponseDTO(); dto.setNoticeId(notice.getIdNotice()); dto.setTitle(notice.getTitle()); dto.setClientId(notice.getClient().getId()); @@ -69,20 +68,30 @@ public class NoticeService { dto.setCategory(notice.getCategory()); dto.setStatus(notice.getStatus()); dto.setPublishDate(notice.getPublishDate()); - dto.setAttributesNotices(notice.getAttributesNotices()); - dto.setWishlisted(isWishlisted); + + List attributes = new ArrayList<>(); + if (notice.getAttributesNotices() != null) { + for (AttributesNotice an : notice.getAttributesNotices()) { + AttributeDto attr = new AttributeDto(); + attr.setName(an.getAttributeValue().getAttribute().getName()); + attr.setValue(an.getAttributeValue().getValue()); + attributes.add(attr); + } + } + dto.setAttributes(attributes); + return dto; } - public List getAllNotices() { - List result = new ArrayList<>(); + public List getAllNotices() { + List result = new ArrayList<>(); for (Notice notice : noticeRepository.findAll()) { result.add(toDTO(notice)); } return result; } - public NoticeDTO getNoticeById(Long id) { + public NoticeResponseDTO getNoticeById(Long id) { Notice notice = noticeRepository.findById(id) .orElseThrow(() -> new EntityNotFoundException("Nie znaleziono ogłoszenia o ID: " + id)); return toDTO(notice); @@ -93,15 +102,48 @@ public class NoticeService { .orElseThrow(() -> new EntityNotFoundException("Nie znaleziono ogłoszenia o ID: " + id)); } - public Long addNotice(NoticeDTO dto) { - return noticeRepository.save(fromDTO(dto)).getIdNotice(); + public Long addNotice(NoticeRequestDTO dto) { + Notice notice = fromDTO(dto); + notice.setPublishDate(LocalDateTime.now()); + Notice savedNotice = noticeRepository.save(notice); + + if (dto.getAttributes() != null && !dto.getAttributes().isEmpty()) { + saveAttributes(savedNotice.getIdNotice(), dto.getAttributes()); + } + + return savedNotice.getIdNotice(); + } + + private void saveAttributes(Long noticeId, List attributeDtos) { + for (AttributeDto attributeDto : attributeDtos) { + Attributes attribute = attributesRepository.findByName(attributeDto.getName()) + .orElseGet(() -> { + Attributes newAttribute = new Attributes(); + newAttribute.setName(attributeDto.getName()); + return attributesRepository.save(newAttribute); + }); + + AttributeValues attributeValue = attributeValuesRepository + .findByAttributeAndValue(attribute, attributeDto.getValue()) + .orElseGet(() -> { + AttributeValues newValue = new AttributeValues(); + newValue.setAttribute(attribute); + newValue.setValue(attributeDto.getValue()); + return attributeValuesRepository.save(newValue); + }); + + AttributesNotice attributesNotice = new AttributesNotice(); + attributesNotice.setNotice_id(noticeId); + attributesNotice.setAttributeValue(attributeValue); + attributesNoticeRepository.save(attributesNotice); + } } public boolean noticeExists(Long id) { return noticeRepository.existsById(id); } - public NoticeDTO updateNotice(Long id, NoticeDTO dto) { + public NoticeResponseDTO updateNotice(Long id, NoticeRequestDTO dto) { Notice existingNotice = noticeRepository.findById(id) .orElseThrow(() -> new EntityNotFoundException("Nie znaleziono ogłoszenia o ID: " + id)); @@ -110,7 +152,6 @@ public class NoticeService { existingNotice.setPrice(dto.getPrice()); existingNotice.setCategory(dto.getCategory()); existingNotice.setStatus(dto.getStatus()); - existingNotice.setAttributesNotices(dto.getAttributesNotices()); if (dto.getClientId() != null && !dto.getClientId().equals(existingNotice.getClient().getId())) { Client client = clientRepository.findById(dto.getClientId()) diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/service/OrderService.java b/src/main/java/_11/asktpk/artisanconnectbackend/service/OrderService.java index 5a97f98..c77e5fc 100644 --- a/src/main/java/_11/asktpk/artisanconnectbackend/service/OrderService.java +++ b/src/main/java/_11/asktpk/artisanconnectbackend/service/OrderService.java @@ -13,6 +13,7 @@ import org.springframework.stereotype.Service; import _11.asktpk.artisanconnectbackend.entities.Order; import java.time.LocalDateTime; +import java.util.List; @Service public class OrderService { @@ -56,8 +57,7 @@ public class OrderService { public Long addOrder(OrderDTO orderDTO) { - Order order = fromDTO(orderDTO); - return orderRepository.save(order).getId(); + return orderRepository.save(fromDTO(orderDTO)).getId(); } public Long changeOrderStatus(Long id, Enums.OrderStatus status) { @@ -76,4 +76,8 @@ public class OrderService { return orderRepository.findById(id) .orElseThrow(() -> new RuntimeException("Nie znaleziono zamówienia o ID: " + id)); } + + public List getOrdersByClientId(Long clientId) { + return orderRepository.findByClientId(clientId); + } } diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/service/PaymentService.java b/src/main/java/_11/asktpk/artisanconnectbackend/service/PaymentService.java index aee6bd5..3811277 100644 --- a/src/main/java/_11/asktpk/artisanconnectbackend/service/PaymentService.java +++ b/src/main/java/_11/asktpk/artisanconnectbackend/service/PaymentService.java @@ -15,6 +15,8 @@ import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; +import java.util.List; + @Service public class PaymentService { private final WebClient webClient; @@ -80,4 +82,10 @@ public class PaymentService { return null; } + + public List getPaymentsByOrderId(Long id) { + return paymentRepository.findAllByOrderId(id); + } + + } diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/service/WishlistService.java b/src/main/java/_11/asktpk/artisanconnectbackend/service/WishlistService.java index 781a92f..4c9659d 100644 --- a/src/main/java/_11/asktpk/artisanconnectbackend/service/WishlistService.java +++ b/src/main/java/_11/asktpk/artisanconnectbackend/service/WishlistService.java @@ -1,7 +1,7 @@ package _11.asktpk.artisanconnectbackend.service; import _11.asktpk.artisanconnectbackend.dto.WishlistDTO; -import _11.asktpk.artisanconnectbackend.dto.NoticeDTO; +import _11.asktpk.artisanconnectbackend.dto.NoticeResponseDTO; import _11.asktpk.artisanconnectbackend.entities.Client; import _11.asktpk.artisanconnectbackend.entities.Notice; import _11.asktpk.artisanconnectbackend.entities.Wishlist; @@ -31,12 +31,6 @@ public class WishlistService { .toList(); } - public boolean isWishlisted(Client client, Notice notice) { - Optional existingEntry = wishlistRepository.findByClientAndNotice(client, notice); - - return existingEntry.isEmpty(); - } - public boolean toggleWishlist(Client client, Notice notice) { Optional existingEntry = wishlistRepository.findByClientAndNotice(client, notice); @@ -61,7 +55,7 @@ public class WishlistService { return dto; } - public List getNoticesInWishlist(Long clientId) { + public List getNoticesInWishlist(Long clientId) { List wishlistEntries = wishlistRepository.findAllByClientId(clientId); return wishlistEntries.stream() diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/utils/Tools.java b/src/main/java/_11/asktpk/artisanconnectbackend/utils/Tools.java new file mode 100644 index 0000000..416dc91 --- /dev/null +++ b/src/main/java/_11/asktpk/artisanconnectbackend/utils/Tools.java @@ -0,0 +1,24 @@ +package _11.asktpk.artisanconnectbackend.utils; + +import _11.asktpk.artisanconnectbackend.security.JwtUtil; + +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.stereotype.Component; + +@Component +public class Tools { + private final JwtUtil jwtUtil; + + public Tools(JwtUtil jwtUtil) { + this.jwtUtil = jwtUtil; + } + + public Long getClientIdFromRequest(HttpServletRequest request) { + String authorizationHeader = request.getHeader("Authorization"); + if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) { + return jwtUtil.extractUserId(authorizationHeader.substring(7)); + } else { + return -1L; + } + } +} diff --git a/src/main/resources/sql/data.sql b/src/main/resources/sql/data.sql index d9c2989..c889d10 100644 --- a/src/main/resources/sql/data.sql +++ b/src/main/resources/sql/data.sql @@ -17,4 +17,45 @@ INSERT INTO notice (title, description, client_id, price, category, status, publ ('Drewniany stół', 'Solidny stół wykonany z litego drewna dębowego.', 3, 1200.00, 'Furniture', 'ACTIVE', '2023-09-15'), ('Ceramiczna waza', 'Piękna waza ceramiczna, idealna na prezent.', 2, 300.00, 'Ceramics', 'INACTIVE', '2023-08-20'), ('Obraz olejny', 'Obraz olejny przedstawiający krajobraz górski.', 4, 800.00, 'Painting', 'ACTIVE', '2023-07-10'), - ('Skórzany portfel', 'Ręcznie wykonany portfel ze skóry naturalnej.', 1, 250.00, 'Leatherwork', 'ACTIVE', '2023-06-05'); \ No newline at end of file + ('Skórzany portfel', 'Ręcznie wykonany portfel ze skóry naturalnej.', 1, 250.00, 'Leatherwork', 'ACTIVE', '2023-06-05'); + + +insert into attributes (name) values + ('Kolor'), + ('Materiał'); + +-- Kolory +insert into attribute_values (value, id_attribute) values + ('Zielony', 1), + ('Czerwony', 1), + ('Niebieski', 1), + ('Żółty', 1), + ('Biały', 1), + ('Czarny', 1), + ('Różowy', 1), + ('Szary', 1), + ('Fioletowy', 1), + ('Pomarańczowy', 1), + ('Inny', 1); + +-- Materiały +insert into attribute_values (value, id_attribute) values + ('Bawełna', 2), + ('Wełna', 2), + ('Syntetyk', 2), + ('Skóra', 2), + ('Len', 2), + ('Jedwab', 2), + ('Poliester', 2), + ('Akryl', 2), + ('Wiskoza', 2), + ('Nylon', 2), + ('Inny', 2); + +insert into attributes_notice (id_value, notice_id) values + (1, 1), -- Ręcznie robiona biżuteria - Zielony + (22, 1), + (2, 2), -- Drewniany stół - Czerwony + (3, 3), -- Ceramiczna waza - Niebieski + (4, 4), -- Obraz olejny - Żółty + (5, 5); -- Skórzany portfel - Biały