Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,4 @@ yarn-error.log*
#ignore coverage folder
coverage/
#ignore .next folder
.next/
cls
.next/
Binary file modified README.md
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import jakarta.validation.constraints.FutureOrPresent;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.PastOrPresent;
import jakarta.validation.constraints.Positive;

import java.time.LocalDate;
Expand All @@ -23,15 +24,21 @@ public record CreateInventoryDto(
@NotNull(message = "Product reserve available is required")
Integer reservedQuantity, //by default, it is 1

@PastOrPresent(message = "Manufactured date must be a past or present date")
@NotNull(message = "Manufactured date is required")
LocalDate manufacturedDate,

/**
* //Todo: add the product expiry date to this record because it should
* //Done: add the product expiry date to this record because it should
* not be possible to add inventory for an expired product
* It should not be possible to add inventory for an expired product.
*/
@NotNull(message = "Expiry date is required")
@FutureOrPresent(message = "Expiry date must be a future or present date")
LocalDate expiryDate



) {


Expand Down
1 change: 1 addition & 0 deletions common-utils/src/main/java/com/tjtechy/ProductDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public record ProductDto(
String productDescription,
Integer productQuantity,
Integer availableStock,
LocalDate manufacturedDate,
LocalDate expiryDate,
BigDecimal productPrice

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public void createInventoryForProductAsync(CreateInventoryDto createInventoryDto

/**
* Restores inventory for a given product by the specified quantity.
* This method is typically called when an order is cancelled, returned, or updated,
* This method is typically called when an order is canceled, returned, or updated,
* and the inventory needs to be restored.
* @param productId the UUID of the product
* @param quantityToRestore the quantity to restore to inventory
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
* @Version = 1.0
* This file is part of EcommerceMicroservices module of the Ecommerce Microservices project.
*/
package com.tjtechy.events.orderEvent;

package com.tjtechy.notification_service.listener;

public class OrderEventListener {
public enum ActionBy {
USER,
ADMIN,
SYSTEM
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,20 @@

package com.tjtechy.events.orderEvent;

import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;

import java.time.LocalDate;

public record OrderCancelledEvent(
Long orderId,
String customerEmail,
String customDeviceToken,
String customerPhoneNumber
String customerPhoneNumber,
LocalDate cancellationDate,
@Enumerated(EnumType.STRING)
ActionBy actionBy,
@Enumerated(EnumType.STRING)
Reason reason
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Copyright © 2025
*
* @Author = TJTechy (Tajudeen Busari)
* @Version = 1.0
* This file is part of EcommerceMicroservices module of the Ecommerce Microservices project.
*/

package com.tjtechy.events.orderEvent;

import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;

import java.time.LocalDate;

public record OrderDeletedEvent(
Long orderId,
String customerEmail,
String customDeviceToken,
String customerPhoneNumber,
@Enumerated(EnumType.STRING)
Reason reason, /// USER_REQUEST, ADMIN_ACTION, SYSTEM_CLEANUP, FRAUD_DETECTION, OTHER
@Enumerated(EnumType.STRING)
ActionBy deletedBy, /// e.g., "USER", "ADMIN", "SYSTEM"
LocalDate deletionDate
) {

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,20 @@

package com.tjtechy.events.orderEvent;

import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;

import java.time.LocalDate;

public record OrderPlacedEvent(
Long orderId,
String customerEmail,
String customDeviceToken,
String customerPhoneNumber
String customerPhoneNumber,
LocalDate orderDate,
@Enumerated(EnumType.STRING)
ActionBy actionBy,
@Enumerated(EnumType.STRING)
Reason reason
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Copyright © 2025
*
* @Author = TJTechy (Tajudeen Busari)
* @Version = 1.0
* This file is part of EcommerceMicroservices module of the Ecommerce Microservices project.
*/

package com.tjtechy.events.orderEvent;

import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;

import java.time.LocalDate;

public record OrderUpdatedEvent(
Long orderId,
String customerEmail,
String customDeviceToken,
String customerPhoneNumber,
@Enumerated(EnumType.STRING)
ActionBy actionBy,
@Enumerated(EnumType.STRING)
Reason reason,
LocalDate updatedDate
) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Copyright © 2025
*
* @Author = TJTechy (Tajudeen Busari)
* @Version = 1.0
* This file is part of EcommerceMicroservices module of the Ecommerce Microservices project.
*/
package com.tjtechy.events.orderEvent;

public enum Reason {
USER_REQUEST,
ADMIN_ACTION,
SYSTEM_CLEANUP,
FRAUD_DETECTION,
OTHER
}
Binary file modified common-utils/target/classes/com/tjtechy/CreateInventoryDto.class
Binary file not shown.
Binary file modified common-utils/target/classes/com/tjtechy/ProductDto.class
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified common-utils/target/common-utils-0.0.1.jar
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ com\tjtechy\events\orderEvent\OrderPlacedEvent.class
com\tjtechy\UpdateInventoryDto.class
com\tjtechy\InventoryDto.class
com\tjtechy\DeductInventoryRequestDto.class
com\tjtechy\events\orderEvent\OrderDeletedEvent.class
com\tjtechy\RestoreInventoryDto.class
com\tjtechy\events\orderEvent\OrderUpdatedEvent.class
com\tjtechy\client\InventoryServiceClient.class
com\tjtechy\config\InventoryServiceConfig.class
com\tjtechy\events\orderEvent\OrderCancelledEvent.class
com\tjtechy\RedisCacheConfig.class
com\tjtechy\client\ProductServiceClient.class
com\tjtechy\ProductDto.class
com\tjtechy\config\ProductServiceConfig.class
com\tjtechy\events\orderEvent\ActionBy.class
com\tjtechy\Inventory.class
com\tjtechy\CreateInventoryDto.class
com\tjtechy\events\orderEvent\Reason.class
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ C:\Users\tajud\javaProject\EcommerceMicroservices\common-utils\src\main\java\com
C:\Users\tajud\javaProject\EcommerceMicroservices\common-utils\src\main\java\com\tjtechy\config\ProductServiceConfig.java
C:\Users\tajud\javaProject\EcommerceMicroservices\common-utils\src\main\java\com\tjtechy\CreateInventoryDto.java
C:\Users\tajud\javaProject\EcommerceMicroservices\common-utils\src\main\java\com\tjtechy\DeductInventoryRequestDto.java
C:\Users\tajud\javaProject\EcommerceMicroservices\common-utils\src\main\java\com\tjtechy\events\orderEvent\ActionBy.java
C:\Users\tajud\javaProject\EcommerceMicroservices\common-utils\src\main\java\com\tjtechy\events\orderEvent\OrderCancelledEvent.java
C:\Users\tajud\javaProject\EcommerceMicroservices\common-utils\src\main\java\com\tjtechy\events\orderEvent\OrderDeletedEvent.java
C:\Users\tajud\javaProject\EcommerceMicroservices\common-utils\src\main\java\com\tjtechy\events\orderEvent\OrderPlacedEvent.java
C:\Users\tajud\javaProject\EcommerceMicroservices\common-utils\src\main\java\com\tjtechy\events\orderEvent\OrderUpdatedEvent.java
C:\Users\tajud\javaProject\EcommerceMicroservices\common-utils\src\main\java\com\tjtechy\events\orderEvent\Reason.java
C:\Users\tajud\javaProject\EcommerceMicroservices\common-utils\src\main\java\com\tjtechy\Inventory.java
C:\Users\tajud\javaProject\EcommerceMicroservices\common-utils\src\main\java\com\tjtechy\InventoryDto.java
C:\Users\tajud\javaProject\EcommerceMicroservices\common-utils\src\main\java\com\tjtechy\ProductDto.java
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,9 @@ private List<CreateInventoryDto> createInventoryDtoList (int count){
UUID.randomUUID(), // Randomly generate a productId
faker.number().numberBetween(1, 100), // Randomly generate a reserve quantity between 1 and 100
faker.number().numberBetween(1, 100),// Randomly generate available stock
LocalDate.now().plusDays(30)
LocalDate.now(), // Set manufactured date to today and before expiry date
LocalDate.now().plusDays(30) // Set expiry date to 30 days in the future


);
inventoryDtoList.add(createInventoryDto);
Expand Down Expand Up @@ -174,7 +176,9 @@ public void testCreateInventorySuccess() throws Exception {
UUID.randomUUID(), // Randomly generate a productId
faker.number().numberBetween(1, 100), // Randomly generate a quantity between 1 and 100
faker.number().numberBetween(1, 100),// Randomly generate a reserved quantity
LocalDate.now(), // Set manufactured date to today and before expiry date
LocalDate.now().plusDays(30) // Set expiry date to 30 days in the future

);
Map<String, Object> savedInventory = createInventory(createInventoryDto);
assertThat(savedInventory).isNotNull();
Expand All @@ -197,7 +201,9 @@ public void testGetInventoryByIdSuccess() throws Exception {
UUID.randomUUID(), // Randomly generate a productId
faker.number().numberBetween(1, 100), // Randomly generate a quantity between 1 and 100
faker.number().numberBetween(1, 100), // Randomly generate a reserved quantity
LocalDate.now().plusDays(365) // Set expiry date to 30 days in the future
LocalDate.now(), // Set manufactured date to today and before expiry date
LocalDate.now().plusDays(365)// Set expiry date to 30 days in the future

);
Map<String, Object> savedInventory = createInventory(createInventoryDto);

Expand Down Expand Up @@ -248,7 +254,9 @@ public void testGetInventoryByProductIdSuccess() throws Exception {
UUID.randomUUID(), // Randomly generate a productId
faker.number().numberBetween(1, 100), // Randomly generate a quantity between 1 and 100
faker.number().numberBetween(1, 100), // Randomly generate a reserved quantity
LocalDate.now(), // Set manufactured date to today
LocalDate.now().plusDays(365) // Set expiry date to 30 days in the future

);
Map<String, Object> savedInventory = createInventory(createInventoryDto);

Expand Down Expand Up @@ -290,7 +298,9 @@ public void testUpdateInventorySuccess() throws Exception {
UUID.randomUUID(), // Randomly generate a productId
faker.number().numberBetween(1, 100), // Randomly generate a quantity between 1 and 100
faker.number().numberBetween(1, 100), // Randomly generate a reserved quantity
LocalDate.now().plusDays(365) // Set expiry date to 30 days in the future
LocalDate.now(), // Set manufactured date to today
LocalDate.now().plusDays(365)// Set expiry date to 30 days in the future

);
Map<String, Object> savedInventory = createInventory(createInventoryDto); //inventoryDto

Expand Down Expand Up @@ -327,7 +337,9 @@ public void testDeleteInventorySuccess() throws Exception {
UUID.randomUUID(), // Randomly generate a productId
faker.number().numberBetween(1, 100), // Randomly generate a quantity between 1 and 100
faker.number().numberBetween(1, 100),// Randomly generate a reserved quantity
LocalDate.now(), // Set manufactured date to today
LocalDate.now().plusDays(365) // Set expiry date to 30 days in the future

);
Map<String, Object> savedInventory = createInventory(createInventoryDto);

Expand Down Expand Up @@ -375,7 +387,9 @@ public void testDeductInventorySuccess() throws Exception {
UUID.randomUUID(), // Randomly generate a productId
faker.number().numberBetween(1, 100), // Randomly generate a quantity between 1 and 100
faker.number().numberBetween(1, 100), // Randomly generate a reserved quantity
LocalDate.now(), // Set manufactured date to today
LocalDate.now().plusDays(365) // Set expiry date to 30 days in the future

);
Map<String, Object> savedInventory = createInventory(createInventoryDto);

Expand Down Expand Up @@ -415,7 +429,9 @@ public void testRestoreInventorySuccess() throws Exception {
UUID.randomUUID(), // Randomly generate a productId
faker.number().numberBetween(1, 100), // Randomly generate a quantity between 1 and 100
faker.number().numberBetween(1, 100),// Randomly generate a reserved quantity
LocalDate.now(), // Set manufactured date to today and before expiry date
LocalDate.now().plusDays(365) // Set expiry date to 30 days in the future

);
Map<String, Object> savedInventory = createInventory(createInventoryDto);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,9 @@ void testAddInventorySuccess() throws Exception {
UUID.randomUUID(),
10,
5,
LocalDate.now().minusDays(1), //manufactured date and comes before expiry date
LocalDate.now().plusYears(1)

);
var json = objectMapper.writeValueAsString(createInventoryDto);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
package com.tjtechy.notification_service.service.impl;

import com.tjtechy.events.orderEvent.OrderCancelledEvent;
import com.tjtechy.events.orderEvent.OrderDeletedEvent;
import com.tjtechy.events.orderEvent.OrderPlacedEvent;
import com.tjtechy.events.orderEvent.OrderUpdatedEvent;
import com.tjtechy.notification_service.config.MailProperties;
import com.tjtechy.notification_service.entity.Notification;
import com.tjtechy.notification_service.repository.NotificationRepository;
Expand Down Expand Up @@ -137,4 +139,30 @@ public void listenToOrderCancelled(OrderCancelledEvent event){
String message = "Your order with ID " + event.orderId() + " has been cancelled.";
processNotification(event.customerEmail(), "Order Cancellation Notice", message, event.orderId());
}

/**
* Listens to order deleted events from Kafka topic and processes email notification
* The groupId is set to email-notification-group to ensure to differentiate from other notification services,
* e.g., push notification service. The default value is defined in application.yml: notification-service-group
* @param event
*/
@KafkaListener(topics= "${spring.kafka.topics.order-deleted}", groupId = "email-notification-group")
public void listenToOrderDeleted(OrderDeletedEvent event){
logger.info("Received order deleted event: {}", event);
String message = "Your order with ID " + event.orderId() + " has been deleted.";
processNotification(event.customerEmail(), "Order Deletion Notice", message, event.orderId());
}

/**
* Listens to order updated events from Kafka topic and processes email notification
* The groupId is set to email-notification-group to ensure to differentiate from other notification services,
* e.g., push notification service. The default value is defined in application.yml: notification-service-group
* @param event
*/
@KafkaListener(topics= "${spring.kafka.topics.order-updated}", groupId = "email-notification-group")
public void listenToOrderUpdated(OrderUpdatedEvent event){
logger.info("Received order updated event: {}", event);
String message = "Your order with ID " + event.orderId() + " has been updated.";
processNotification(event.customerEmail(), "Order Update Notice", message, event.orderId());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
import com.google.firebase.messaging.FirebaseMessaging;
import com.google.firebase.messaging.Message;
import com.tjtechy.events.orderEvent.OrderCancelledEvent;
import com.tjtechy.events.orderEvent.OrderDeletedEvent;
import com.tjtechy.events.orderEvent.OrderPlacedEvent;
import com.tjtechy.events.orderEvent.OrderUpdatedEvent;
import com.tjtechy.notification_service.entity.Notification;
import com.tjtechy.notification_service.repository.NotificationRepository;
import com.tjtechy.notification_service.service.ChannelNotificationService;
Expand Down Expand Up @@ -100,4 +102,31 @@ public void listenToOrderCancelled(OrderCancelledEvent event) {
String message = "Your order with ID " + event.orderId() + " has been cancelled.";
processNotification(event.customDeviceToken(), "Order Cancelled", message, event.orderId());
}

/**
* Listens to order updated events from Kafka topic and processes push notification
* The groupId is set to push-notification-group to ensure to differentiate from other notification services,
* e.g., email notification service. The default value is defined in application.yml: notification-service-group
* @param event
*/
@KafkaListener(topics= "${spring.kafka.topics.order-updated}", groupId = "push-notification-group")
public void listenToOrderUpdated(OrderUpdatedEvent event){
logger.info("Received order updated event: {}", event);
String message = "Your order with ID " + event.orderId() + " has been updated.";
processNotification(event.customDeviceToken(), "Order Update Notice", message, event.orderId());
}

/**
* Listens to order deleted events from Kafka topic and processes push notification
* The groupId is set to push-notification-group to ensure to differentiate from other notification services,
* e.g., email notification service. The default value is defined in application.yml: notification-service-group
* @param event
*/
@KafkaListener(topics= "${spring.kafka.topics.order-deleted}", groupId = "push-notification-group")
public void listenToOrderDeleted(OrderDeletedEvent event){
logger.info("Received order deleted event: {}", event);
String message = "Your order with ID " + event.orderId() + " has been deleted.";
processNotification(event.customDeviceToken(), "Order Deletion Notice", message, event.orderId());
}

}
Loading