Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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