diff --git a/services/contracts/pom.xml b/services/contracts/pom.xml
index a377bb9a..2a000b1c 100644
--- a/services/contracts/pom.xml
+++ b/services/contracts/pom.xml
@@ -20,6 +20,10 @@
21
+
+ org.springframework.boot
+ spring-boot-starter-amqp
+
org.springframework.boot
spring-boot-starter-web
@@ -36,17 +40,57 @@
org.springframework.boot
- spring-boot-starter-data-cassandra
+ spring-boot-testcontainers
+ test
- org.springframework.boot
- spring-boot-starter-amqp
+ org.testcontainers
+ junit-jupiter
+ 1.19.7
+ test
+
+
+ org.testcontainers
+ cassandra
+ 1.19.7
+ test
+
+
+ org.testcontainers
+ rabbitmq
+ 1.19.7
+ test
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-xml
+ 2.16.0
org.springframework.amqp
spring-rabbit-test
test
+
+ org.springframework.boot
+ spring-boot-starter-data-cassandra
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+ 3.1.2
+
+
+ com.redis.testcontainers
+ testcontainers-redis-junit-jupiter
+ 1.4.6
+ test
+
+
+ redis.clients
+ jedis
+ 3.7.0
+
org.projectlombok
lombok
diff --git a/services/contracts/src/main/java/com/workup/contracts/ContractsApplication.java b/services/contracts/src/main/java/com/workup/contracts/ContractsApplication.java
index f4d5087c..fac6783f 100644
--- a/services/contracts/src/main/java/com/workup/contracts/ContractsApplication.java
+++ b/services/contracts/src/main/java/com/workup/contracts/ContractsApplication.java
@@ -12,9 +12,13 @@
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
+@ComponentScan(basePackages = "com.workup")
+@EnableCaching
public class ContractsApplication {
public static void main(String[] args) {
diff --git a/services/contracts/src/main/java/com/workup/contracts/commands/ContractCommand.java b/services/contracts/src/main/java/com/workup/contracts/commands/ContractCommand.java
index b2fef076..998734e3 100644
--- a/services/contracts/src/main/java/com/workup/contracts/commands/ContractCommand.java
+++ b/services/contracts/src/main/java/com/workup/contracts/commands/ContractCommand.java
@@ -6,14 +6,20 @@
import com.workup.shared.commands.Command;
import com.workup.shared.commands.CommandRequest;
import com.workup.shared.commands.CommandResponse;
+import com.workup.shared.redis.RedisService;
import lombok.Setter;
+import org.springframework.amqp.core.AmqpTemplate;
public abstract class ContractCommand
implements Command {
+ @Setter AmqpTemplate rabbitTemplate;
+
@Setter ContractRepository contractRepository;
@Setter ContractMilestoneRepository contractMilestoneRepository;
@Setter TerminationRequestRepository terminationRequestRepository;
+
+ @Setter RedisService redisService;
}
diff --git a/services/contracts/src/main/java/com/workup/contracts/commands/ContractCommandMap.java b/services/contracts/src/main/java/com/workup/contracts/commands/ContractCommandMap.java
index acacec8e..1f12ad3b 100644
--- a/services/contracts/src/main/java/com/workup/contracts/commands/ContractCommandMap.java
+++ b/services/contracts/src/main/java/com/workup/contracts/commands/ContractCommandMap.java
@@ -6,6 +6,8 @@
import com.workup.shared.commands.CommandMap;
import com.workup.shared.commands.CommandRequest;
import com.workup.shared.commands.CommandResponse;
+import com.workup.shared.redis.RedisService;
+import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -19,6 +21,10 @@ public class ContractCommandMap
@Autowired TerminationRequestRepository terminationRequestRepository;
+ @Autowired AmqpTemplate rabbitTemplate;
+
+ @Autowired RedisService redisService;
+
public void registerCommands() {
commands.put("InitiateContract", InitiateContractCommand.class);
commands.put("RequestContractTermination", RequestContractTerminationCommand.class);
@@ -34,5 +40,7 @@ public void setupCommand(
command.setContractRepository(contractRepository);
command.setContractMilestoneRepository(contractMilestoneRepository);
command.setTerminationRequestRepository(terminationRequestRepository);
+ command.setRabbitTemplate(rabbitTemplate);
+ command.setRedisService(redisService);
}
}
diff --git a/services/contracts/src/main/java/com/workup/contracts/commands/EvaluateMilestoneCommand.java b/services/contracts/src/main/java/com/workup/contracts/commands/EvaluateMilestoneCommand.java
new file mode 100644
index 00000000..f5df099d
--- /dev/null
+++ b/services/contracts/src/main/java/com/workup/contracts/commands/EvaluateMilestoneCommand.java
@@ -0,0 +1,82 @@
+package com.workup.contracts.commands;
+
+import com.workup.contracts.logger.ContractsLogger;
+import com.workup.contracts.models.Contract;
+import com.workup.contracts.models.ContractMilestone;
+import com.workup.shared.commands.contracts.requests.EvaluateMilestoneRequest;
+import com.workup.shared.commands.contracts.responses.EvaluateMilestoneResponse;
+import com.workup.shared.commands.payments.paymentrequest.requests.CreatePaymentRequestRequest;
+import com.workup.shared.enums.HttpStatusCode;
+import com.workup.shared.enums.ServiceQueueNames;
+import com.workup.shared.enums.contracts.MilestoneState;
+import java.util.Optional;
+import java.util.UUID;
+
+public class EvaluateMilestoneCommand
+ extends ContractCommand {
+ private EvaluateMilestoneResponse isValid(Optional milestoneOptional) {
+ if (milestoneOptional.isEmpty())
+ return EvaluateMilestoneResponse.builder()
+ .withStatusCode(HttpStatusCode.BAD_REQUEST)
+ .withErrorMessage("Milestone is not found")
+ .build();
+ if (milestoneOptional.get().getStatus() != MilestoneState.IN_REVIEW)
+ return EvaluateMilestoneResponse.builder()
+ .withStatusCode(HttpStatusCode.BAD_REQUEST)
+ .withErrorMessage("Milestone cannot be evaluated as it has not progressed enough")
+ .build();
+ return null;
+ }
+
+ @Override
+ public EvaluateMilestoneResponse Run(EvaluateMilestoneRequest request) {
+ Optional milestoneOptional =
+ contractMilestoneRepository.findById(UUID.fromString(request.getMilestoneId()));
+
+ EvaluateMilestoneResponse checkerResponse = isValid(milestoneOptional);
+ if (checkerResponse != null) return checkerResponse;
+
+ ContractMilestone updatedMilestone = milestoneOptional.get();
+
+ updatedMilestone.setStatus(request.getEvaluatedState());
+
+ try {
+ contractMilestoneRepository.save(updatedMilestone);
+ ContractsLogger.print(" [x] Milestone evaluated " + updatedMilestone);
+
+ if (request.getEvaluatedState() == MilestoneState.ACCEPTED) {
+ ContractsLogger.print(" [x] Sending payment request ");
+ // Getting the contract as we need to send the freelancer and client id since they are
+ // in the payment request parameters.
+ Optional contractOptional =
+ contractRepository.findById(UUID.fromString(updatedMilestone.getContractId()));
+ if (contractOptional.isEmpty())
+ throw new Exception("Contract Optional was empty, therefore unable to fetch data");
+
+ Contract milestoneContract = contractOptional.get();
+
+ CreatePaymentRequestRequest externalRequest =
+ CreatePaymentRequestRequest.builder()
+ .withAmount(updatedMilestone.getAmount())
+ .withClientId(milestoneContract.getClientId())
+ .withFreelancerId(milestoneContract.getFreelancerId())
+ .withDescription(updatedMilestone.getMilestoneId().toString())
+ .build();
+ rabbitTemplate.convertSendAndReceive(ServiceQueueNames.PAYMENTS, externalRequest);
+ ContractsLogger.print(" [x] Payment request sent ");
+ }
+
+ return EvaluateMilestoneResponse.builder()
+ .withStatusCode(HttpStatusCode.OK)
+ .withErrorMessage("")
+ .build();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ return EvaluateMilestoneResponse.builder()
+ .withStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR)
+ .withErrorMessage(e.getMessage())
+ .build();
+ }
+ }
+}
diff --git a/services/contracts/src/main/java/com/workup/contracts/commands/GetContractCommand.java b/services/contracts/src/main/java/com/workup/contracts/commands/GetContractCommand.java
new file mode 100644
index 00000000..8621c65e
--- /dev/null
+++ b/services/contracts/src/main/java/com/workup/contracts/commands/GetContractCommand.java
@@ -0,0 +1,54 @@
+package com.workup.contracts.commands;
+
+import com.workup.contracts.logger.ContractsLogger;
+import com.workup.contracts.models.Contract;
+import com.workup.shared.commands.contracts.requests.GetContractRequest;
+import com.workup.shared.commands.contracts.responses.GetContractResponse;
+import com.workup.shared.enums.HttpStatusCode;
+import java.util.Optional;
+import java.util.UUID;
+
+public class GetContractCommand extends ContractCommand {
+
+ @Override
+ public GetContractResponse Run(GetContractRequest request) {
+ String cachingKey = request.getContractId();
+ GetContractResponse cachedResponse =
+ (GetContractResponse) redisService.getValue(cachingKey, GetContractResponse.class);
+ if (cachedResponse != null) {
+ ContractsLogger.print(
+ "[x] Contract request response fetched from cache: " + cachedResponse.toString());
+
+ return cachedResponse;
+ }
+
+ Optional contractOptional =
+ contractRepository.findById(UUID.fromString(request.getContractId()));
+
+ if (contractOptional.isEmpty()) {
+ return GetContractResponse.builder()
+ .withStatusCode(HttpStatusCode.NOT_FOUND)
+ .withErrorMessage("Requested contract does not exist")
+ .build();
+ }
+
+ Contract contract = contractOptional.get();
+
+ GetContractResponse response =
+ GetContractResponse.builder()
+ .withContractId(contract.getContractId().toString())
+ .withProposalId(contract.getProposalId())
+ .withJobId(contract.getJobId())
+ .withJobTitle(contract.getJobTitle())
+ .withClientId(contract.getClientId())
+ .withFreelancerId(contract.getFreelancerId())
+ .withMilestonesIds(contract.getMilestonesIds())
+ .withStatus(contract.getStatus())
+ .withStatusCode(HttpStatusCode.OK)
+ .withErrorMessage("")
+ .build();
+
+ redisService.setValue(cachingKey, response);
+ return response;
+ }
+}
diff --git a/services/contracts/src/main/java/com/workup/contracts/commands/GetMilestoneCommand.java b/services/contracts/src/main/java/com/workup/contracts/commands/GetMilestoneCommand.java
new file mode 100644
index 00000000..3b28b78b
--- /dev/null
+++ b/services/contracts/src/main/java/com/workup/contracts/commands/GetMilestoneCommand.java
@@ -0,0 +1,54 @@
+package com.workup.contracts.commands;
+
+import com.workup.contracts.logger.ContractsLogger;
+import com.workup.contracts.models.ContractMilestone;
+import com.workup.shared.commands.contracts.requests.GetMilestoneRequest;
+import com.workup.shared.commands.contracts.responses.GetMilestoneResponse;
+import com.workup.shared.enums.HttpStatusCode;
+import java.util.Optional;
+import java.util.UUID;
+
+public class GetMilestoneCommand
+ extends ContractCommand {
+
+ @Override
+ public GetMilestoneResponse Run(GetMilestoneRequest request) {
+ String cachingKey = request.getMilestoneId();
+
+ GetMilestoneResponse cachedResponse =
+ (GetMilestoneResponse) redisService.getValue(cachingKey, GetMilestoneResponse.class);
+ if (cachedResponse != null) {
+ ContractsLogger.print(
+ "[x] Milestone request response fetched from cache: " + cachedResponse.toString());
+
+ return cachedResponse;
+ }
+
+ Optional milestoneOptional =
+ contractMilestoneRepository.findById(UUID.fromString(request.getMilestoneId()));
+
+ if (milestoneOptional.isEmpty()) {
+ return GetMilestoneResponse.builder()
+ .withStatusCode(HttpStatusCode.NOT_FOUND)
+ .withErrorMessage("Requested milestone does not exist")
+ .build();
+ }
+
+ ContractMilestone milestone = milestoneOptional.get();
+
+ GetMilestoneResponse response =
+ GetMilestoneResponse.builder()
+ .withContractId(milestone.getContractId())
+ .withMilestoneId(milestone.getMilestoneId().toString())
+ .withAmount(milestone.getAmount())
+ .withDescription(milestone.getDescription())
+ .withDueDate(milestone.getDueDate())
+ .withAmount(milestone.getAmount())
+ .withStatusCode(HttpStatusCode.OK)
+ .withErrorMessage("")
+ .build();
+
+ redisService.setValue(cachingKey, response);
+ return response;
+ }
+}
diff --git a/services/contracts/src/main/java/com/workup/contracts/commands/GetPendingTerminationsCommand.java b/services/contracts/src/main/java/com/workup/contracts/commands/GetPendingTerminationsCommand.java
new file mode 100644
index 00000000..bfcf3470
--- /dev/null
+++ b/services/contracts/src/main/java/com/workup/contracts/commands/GetPendingTerminationsCommand.java
@@ -0,0 +1,53 @@
+package com.workup.contracts.commands;
+
+import com.workup.contracts.logger.ContractsLogger;
+import com.workup.contracts.models.TerminationRequest;
+import com.workup.shared.commands.contracts.requests.GetPendingTerminationsRequest;
+import com.workup.shared.commands.contracts.responses.GetPendingTerminationsResponse;
+import com.workup.shared.enums.HttpStatusCode;
+import java.util.List;
+
+public class GetPendingTerminationsCommand
+ extends ContractCommand {
+
+ @Override
+ public GetPendingTerminationsResponse Run(GetPendingTerminationsRequest request) {
+ String cachingKey = request.getContractId() + "/pending_terminations";
+
+ GetPendingTerminationsResponse cachedResponse =
+ (GetPendingTerminationsResponse)
+ redisService.getValue(cachingKey, GetPendingTerminationsResponse.class);
+ if (cachedResponse != null) {
+ ContractsLogger.print(
+ "[x] Contract terminations response fetched from cache: " + cachedResponse.toString());
+
+ return cachedResponse;
+ }
+
+ List terminationsList =
+ terminationRequestRepository.findByContractId(request.getContractId());
+
+ if (terminationsList.isEmpty()) {
+ return GetPendingTerminationsResponse.builder()
+ .withStatusCode(HttpStatusCode.NOT_FOUND)
+ .withErrorMessage("No pending terminations exist")
+ .build();
+ }
+
+ TerminationRequest terminationRequest = terminationsList.getFirst();
+
+ GetPendingTerminationsResponse response =
+ GetPendingTerminationsResponse.builder()
+ .withRequestId(terminationRequest.getRequestId().toString())
+ .withRequesterId(terminationRequest.getRequesterId())
+ .withContractId(terminationRequest.getContractId())
+ .withReason(terminationRequest.getReason())
+ .withStatus(terminationRequest.getStatus())
+ .withStatusCode(HttpStatusCode.OK)
+ .withErrorMessage("")
+ .build();
+
+ redisService.setValue(cachingKey, response);
+ return response;
+ }
+}
diff --git a/services/contracts/src/main/java/com/workup/contracts/commands/HandleTerminationRequestCommand.java b/services/contracts/src/main/java/com/workup/contracts/commands/HandleTerminationRequestCommand.java
index c55e6fcd..d8fd432d 100644
--- a/services/contracts/src/main/java/com/workup/contracts/commands/HandleTerminationRequestCommand.java
+++ b/services/contracts/src/main/java/com/workup/contracts/commands/HandleTerminationRequestCommand.java
@@ -1,5 +1,6 @@
package com.workup.contracts.commands;
+import com.workup.contracts.logger.ContractsLogger;
import com.workup.contracts.models.Contract;
import com.workup.contracts.models.TerminationRequest;
import com.workup.shared.commands.contracts.requests.HandleTerminationRequest;
@@ -41,7 +42,7 @@ private HandleTerminationResponse handleTerminationRequest(
}
try {
TerminationRequest updatedRequest = terminationRequestRepository.save(terminationRequest);
- System.out.println(" [x] Updated Termination Request " + updatedRequest);
+ ContractsLogger.print(" [x] Updated Termination Request " + updatedRequest);
return HandleTerminationResponse.builder()
.withRequestStatus(updatedRequest.getStatus())
.withStatusCode(HttpStatusCode.OK)
@@ -67,7 +68,7 @@ private HandleTerminationResponse terminateContract(String contractId) {
updatedContract.setStatus(ContractState.TERMINATED);
try {
updatedContract = contractRepository.save(updatedContract);
- System.out.println(" [x] Updated Contract Status to Terminated " + updatedContract);
+ ContractsLogger.print(" [x] Updated Contract Status to Terminated " + updatedContract);
} catch (Exception e) {
e.printStackTrace();
return HandleTerminationResponse.builder()
diff --git a/services/contracts/src/main/java/com/workup/contracts/commands/InitiateContractCommand.java b/services/contracts/src/main/java/com/workup/contracts/commands/InitiateContractCommand.java
index 45a191b5..d85dd4c5 100644
--- a/services/contracts/src/main/java/com/workup/contracts/commands/InitiateContractCommand.java
+++ b/services/contracts/src/main/java/com/workup/contracts/commands/InitiateContractCommand.java
@@ -1,5 +1,6 @@
package com.workup.contracts.commands;
+import com.workup.contracts.logger.ContractsLogger;
import com.workup.contracts.models.Contract;
import com.workup.contracts.models.ContractMilestone;
import com.workup.shared.commands.contracts.Milestone;
@@ -56,11 +57,11 @@ public InitiateContractResponse Run(InitiateContractRequest request) {
try {
Contract savedContract = contractRepository.save(contract);
- System.out.println(" [x] Saved Contract '" + savedContract.getJobTitle());
+ ContractsLogger.print(" [x] Saved Contract '" + savedContract.getJobTitle());
contractMilestoneRepository.saveAll(milestonesToAdd);
- System.out.println(" [x] Saved All Milestones '" + savedContract.getJobTitle());
+ ContractsLogger.print(" [x] Saved All Milestones '" + savedContract.getJobTitle());
return InitiateContractResponse.builder()
.withContractId(savedContract.getContractId().toString())
diff --git a/services/contracts/src/main/java/com/workup/contracts/commands/MarkMilestoneAsPaidCommand.java b/services/contracts/src/main/java/com/workup/contracts/commands/MarkMilestoneAsPaidCommand.java
index 99720855..9922fd13 100644
--- a/services/contracts/src/main/java/com/workup/contracts/commands/MarkMilestoneAsPaidCommand.java
+++ b/services/contracts/src/main/java/com/workup/contracts/commands/MarkMilestoneAsPaidCommand.java
@@ -39,6 +39,7 @@ public MarkPaymentCompletedResponse Run(MarkPaymentCompletedRequest request) {
try {
contractMilestoneRepository.save(updatedMilestone);
System.out.println(" [x] Marked Milestone as Paid '" + updatedMilestone);
+ return MarkPaymentCompletedResponse.builder().withStatusCode(HttpStatusCode.OK).build();
} catch (Exception e) {
e.printStackTrace();
return MarkPaymentCompletedResponse.builder()
@@ -46,8 +47,6 @@ public MarkPaymentCompletedResponse Run(MarkPaymentCompletedRequest request) {
.withErrorMessage(e.getMessage())
.build();
}
-
- return null;
}
private void pay(ContractMilestone milestone) {
diff --git a/services/contracts/src/main/java/com/workup/contracts/commands/ProgressMilestoneCommand.java b/services/contracts/src/main/java/com/workup/contracts/commands/ProgressMilestoneCommand.java
new file mode 100644
index 00000000..3f480e3f
--- /dev/null
+++ b/services/contracts/src/main/java/com/workup/contracts/commands/ProgressMilestoneCommand.java
@@ -0,0 +1,66 @@
+package com.workup.contracts.commands;
+
+import com.workup.contracts.logger.ContractsLogger;
+import com.workup.contracts.models.ContractMilestone;
+import com.workup.shared.commands.contracts.requests.ProgressMilestoneRequest;
+import com.workup.shared.commands.contracts.responses.ProgressMilestoneResponse;
+import com.workup.shared.enums.HttpStatusCode;
+import com.workup.shared.enums.contracts.MilestoneState;
+import java.util.Optional;
+import java.util.UUID;
+
+public class ProgressMilestoneCommand
+ extends ContractCommand {
+
+ private ProgressMilestoneResponse isValid(Optional milestoneOptional) {
+ if (milestoneOptional.isEmpty())
+ return ProgressMilestoneResponse.builder()
+ .withStatusCode(HttpStatusCode.BAD_REQUEST)
+ .withErrorMessage("Milestone is not found")
+ .build();
+
+ MilestoneState milestoneState = milestoneOptional.get().getStatus();
+ if (milestoneState != MilestoneState.OPEN && milestoneState != MilestoneState.IN_PROGRESS)
+ return ProgressMilestoneResponse.builder()
+ .withStatusCode(HttpStatusCode.BAD_REQUEST)
+ .withErrorMessage("Milestone cannot be progressed through this command")
+ .build();
+ return null;
+ }
+
+ @Override
+ public ProgressMilestoneResponse Run(ProgressMilestoneRequest request) {
+ Optional milestoneOptional =
+ contractMilestoneRepository.findById(UUID.fromString(request.getMilestoneId()));
+
+ ProgressMilestoneResponse checkerResponse = isValid(milestoneOptional);
+ if (checkerResponse != null) return checkerResponse;
+
+ ContractMilestone updatedMilestone = milestoneOptional.get();
+
+ progress(updatedMilestone);
+
+ try {
+ contractMilestoneRepository.save(updatedMilestone);
+ ContractsLogger.print(" [x] Milestone Progressed " + updatedMilestone);
+ return ProgressMilestoneResponse.builder()
+ .withStatusCode(HttpStatusCode.OK)
+ .withErrorMessage("")
+ .build();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ return ProgressMilestoneResponse.builder()
+ .withStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR)
+ .withErrorMessage(e.getMessage())
+ .build();
+ }
+ }
+
+ private void progress(ContractMilestone milestone) {
+ if (milestone.getStatus() == MilestoneState.OPEN)
+ milestone.setStatus(MilestoneState.IN_PROGRESS);
+ else if (milestone.getStatus() == MilestoneState.IN_PROGRESS)
+ milestone.setStatus(MilestoneState.IN_REVIEW);
+ }
+}
diff --git a/services/contracts/src/main/java/com/workup/contracts/commands/RequestContractTerminationCommand.java b/services/contracts/src/main/java/com/workup/contracts/commands/RequestContractTerminationCommand.java
index 5eedd8c0..9cd7850d 100644
--- a/services/contracts/src/main/java/com/workup/contracts/commands/RequestContractTerminationCommand.java
+++ b/services/contracts/src/main/java/com/workup/contracts/commands/RequestContractTerminationCommand.java
@@ -1,5 +1,6 @@
package com.workup.contracts.commands;
+import com.workup.contracts.logger.ContractsLogger;
import com.workup.contracts.models.Contract;
import com.workup.contracts.models.TerminationRequest;
import com.workup.shared.commands.contracts.requests.ContractTerminationRequest;
@@ -68,7 +69,7 @@ public ContractTerminationResponse Run(ContractTerminationRequest request) {
try {
TerminationRequest savedRequest = terminationRequestRepository.save(terminationRequest);
- System.out.println(" [x] Saved Termination Request '" + savedRequest);
+ ContractsLogger.print(" [x] Saved Termination Request '" + savedRequest);
return ContractTerminationResponse.builder()
.withRequestId(savedRequest.getRequestId().toString())
diff --git a/services/contracts/src/main/java/com/workup/contracts/logger/ContractsLogger.java b/services/contracts/src/main/java/com/workup/contracts/logger/ContractsLogger.java
new file mode 100644
index 00000000..1e2e71d6
--- /dev/null
+++ b/services/contracts/src/main/java/com/workup/contracts/logger/ContractsLogger.java
@@ -0,0 +1,8 @@
+package com.workup.contracts.logger;
+
+public class ContractsLogger {
+
+ public static void print(String logMessage) {
+ System.out.println(logMessage);
+ }
+}
diff --git a/services/contracts/src/main/java/com/workup/contracts/repositories/TerminationRequestRepository.java b/services/contracts/src/main/java/com/workup/contracts/repositories/TerminationRequestRepository.java
index 16734af9..098dd1e6 100644
--- a/services/contracts/src/main/java/com/workup/contracts/repositories/TerminationRequestRepository.java
+++ b/services/contracts/src/main/java/com/workup/contracts/repositories/TerminationRequestRepository.java
@@ -6,6 +6,7 @@
import java.util.UUID;
import org.springframework.data.cassandra.repository.AllowFiltering;
import org.springframework.data.cassandra.repository.CassandraRepository;
+import org.springframework.data.cassandra.repository.Query;
import org.springframework.stereotype.Repository;
@Repository
@@ -14,4 +15,7 @@ public interface TerminationRequestRepository
@AllowFiltering
List findByRequesterIdAndContractIdAndStatus(
String requesterId, String contractId, TerminationRequestStatus status);
+
+ @Query("SELECT * FROM contracts_data.termination_requests WHERE contractid = ?0")
+ List findByContractId(String contractId);
}
diff --git a/services/contracts/src/test/java/com/workup/contracts/ContractApplicationTests.java b/services/contracts/src/test/java/com/workup/contracts/ContractApplicationTests.java
deleted file mode 100644
index 83a3f093..00000000
--- a/services/contracts/src/test/java/com/workup/contracts/ContractApplicationTests.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.workup.contracts;
-
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.context.SpringBootTest;
-
-@SpringBootTest
-class ContractApplicationTests {
-
- @Test
- void contextLoads() {}
-}
diff --git a/services/contracts/src/test/java/com/workup/contracts/ContractsApplicationTests.java b/services/contracts/src/test/java/com/workup/contracts/ContractsApplicationTests.java
new file mode 100644
index 00000000..ac6e5ec8
--- /dev/null
+++ b/services/contracts/src/test/java/com/workup/contracts/ContractsApplicationTests.java
@@ -0,0 +1,95 @@
+package com.workup.contracts;
+
+import com.workup.contracts.repositories.ContractMilestoneRepository;
+import com.workup.contracts.repositories.ContractRepository;
+import com.workup.contracts.repositories.TerminationRequestRepository;
+import java.text.ParseException;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.amqp.core.AmqpTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Import;
+import org.springframework.test.context.DynamicPropertyRegistry;
+import org.springframework.test.context.DynamicPropertySource;
+import org.testcontainers.containers.CassandraContainer;
+import org.testcontainers.containers.RabbitMQContainer;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+
+@SpringBootTest
+@Testcontainers
+@Import(TestConfigBase.class)
+class ContractsApplicationTests {
+
+ @Container
+ static CassandraContainer> cassandraContainer =
+ new CassandraContainer<>("cassandra:4.0.7").withConfigurationOverride("cassandra-config");
+
+ @Container
+ static RabbitMQContainer rabbitMQContainer = new RabbitMQContainer("rabbitmq:3.13-management");
+
+ static String GetCassandraContactPoint() {
+ return cassandraContainer.getHost() + ":" + cassandraContainer.getFirstMappedPort();
+ }
+
+ @DynamicPropertySource
+ static void datasourceProperties(DynamicPropertyRegistry registry) {
+ registry.add(
+ "spring.cassandra.contact-points", ContractsApplicationTests::GetCassandraContactPoint);
+
+ registry.add("spring.rabbitmq.host", rabbitMQContainer::getHost);
+ registry.add("spring.rabbitmq.port", rabbitMQContainer::getFirstMappedPort);
+ registry.add("spring.rabbitmq.username", rabbitMQContainer::getAdminUsername);
+ registry.add("spring.rabbitmq.password", rabbitMQContainer::getAdminPassword);
+ }
+
+ private static final String CLIENT_ONE_ID = "123";
+ private static final String CLIENT_TWO_ID = "456";
+ private static final String FREELANCER_ONE_ID = "789";
+
+ @Autowired AmqpTemplate template;
+ @Autowired ContractRepository contractRepository;
+ @Autowired ContractMilestoneRepository contractMilestoneRepository;
+ @Autowired TerminationRequestRepository terminationRequestRepository;
+
+ @BeforeEach
+ void clearAll() {
+ contractRepository.deleteAll();
+ contractMilestoneRepository.deleteAll();
+ terminationRequestRepository.deleteAll();
+ }
+
+ /**
+ * Creates a job request.
+ *
+ * @throws ParseException
+ */
+ @Test
+ void testCreateJob() {
+ // Example test from jobs
+ // CreateJobRequest createJobRequest =
+ // CreateJobRequest.builder()
+ // .withTitle("Convert HTML Template to React 3")
+ // .withDescription(
+ // "I have an HTML template that I have purchased and own the rights
+ // to. I would like"
+ // + " it converted into a React application.")
+ // .withSkills(new String[] {"HTML", "CSS", "JavaScript", "React"})
+ // .withUserId(CLIENT_ONE_ID)
+ // .build();
+ //
+ // CreateJobResponse response =
+ // (CreateJobResponse)
+ // template.convertSendAndReceive(ServiceQueueNames.JOBS, createJobRequest);
+ //
+ // assertNotNull(response);
+ // assertTrue(response.getStatusCode() == HttpStatusCode.CREATED);
+ //
+ // jobRepository
+ // .findById(UUID.fromString(response.getJobId()))
+ // .ifPresentOrElse(
+ // job -> assertTrue(job.getTitle().equals(createJobRequest.getTitle())),
+ // () -> new RuntimeException("Job not found"));
+ }
+}
diff --git a/services/contracts/src/test/java/com/workup/contracts/TestConfigBase.java b/services/contracts/src/test/java/com/workup/contracts/TestConfigBase.java
new file mode 100644
index 00000000..acf2801d
--- /dev/null
+++ b/services/contracts/src/test/java/com/workup/contracts/TestConfigBase.java
@@ -0,0 +1,14 @@
+package com.workup.contracts;
+
+import com.workup.shared.enums.ServiceQueueNames;
+import org.springframework.amqp.core.Queue;
+import org.springframework.boot.test.context.TestConfiguration;
+import org.springframework.context.annotation.Bean;
+
+@TestConfiguration
+public class TestConfigBase {
+ @Bean
+ public Queue contractsQueueMock() {
+ return new Queue(ServiceQueueNames.CONTRACTS);
+ }
+}
diff --git a/shared/src/main/java/com/workup/shared/commands/contracts/Milestone.java b/shared/src/main/java/com/workup/shared/commands/contracts/Milestone.java
index 308163c5..159dac47 100644
--- a/shared/src/main/java/com/workup/shared/commands/contracts/Milestone.java
+++ b/shared/src/main/java/com/workup/shared/commands/contracts/Milestone.java
@@ -11,7 +11,7 @@
@Jacksonized
public class Milestone {
- private final String milestoneId; // Not Needed when initiating contract, make it null
+ private final String milestoneId; // Not needed when initiating contract, make it null
private final String contractId; // Not needed when initiating contract, make it null
private final String description;
diff --git a/shared/src/main/java/com/workup/shared/commands/contracts/requests/GetContractRequest.java b/shared/src/main/java/com/workup/shared/commands/contracts/requests/GetContractRequest.java
new file mode 100644
index 00000000..e9ba104e
--- /dev/null
+++ b/shared/src/main/java/com/workup/shared/commands/contracts/requests/GetContractRequest.java
@@ -0,0 +1,14 @@
+package com.workup.shared.commands.contracts.requests;
+
+import com.workup.shared.commands.CommandRequest;
+import lombok.Getter;
+import lombok.experimental.SuperBuilder;
+import lombok.extern.jackson.Jacksonized;
+
+// PURPOSE : To fulfill the need for the read of CRUD for our contract repository
+@Getter
+@SuperBuilder(setterPrefix = "with")
+@Jacksonized
+public class GetContractRequest extends CommandRequest {
+ private final String contractId;
+}
diff --git a/shared/src/main/java/com/workup/shared/commands/contracts/requests/GetMilestoneRequest.java b/shared/src/main/java/com/workup/shared/commands/contracts/requests/GetMilestoneRequest.java
new file mode 100644
index 00000000..6d87533f
--- /dev/null
+++ b/shared/src/main/java/com/workup/shared/commands/contracts/requests/GetMilestoneRequest.java
@@ -0,0 +1,15 @@
+package com.workup.shared.commands.contracts.requests;
+
+import com.workup.shared.commands.CommandRequest;
+import lombok.Getter;
+import lombok.experimental.SuperBuilder;
+import lombok.extern.jackson.Jacksonized;
+
+// PURPOSE : To fulfill the need for the read of CRUD for our milestone repository
+@Getter
+@SuperBuilder(setterPrefix = "with")
+@Jacksonized
+public class GetMilestoneRequest extends CommandRequest {
+
+ private final String milestoneId;
+}
diff --git a/shared/src/main/java/com/workup/shared/commands/contracts/requests/GetPendingTerminationsRequest.java b/shared/src/main/java/com/workup/shared/commands/contracts/requests/GetPendingTerminationsRequest.java
new file mode 100644
index 00000000..c550287c
--- /dev/null
+++ b/shared/src/main/java/com/workup/shared/commands/contracts/requests/GetPendingTerminationsRequest.java
@@ -0,0 +1,14 @@
+package com.workup.shared.commands.contracts.requests;
+
+import com.workup.shared.commands.CommandRequest;
+import lombok.Getter;
+import lombok.experimental.SuperBuilder;
+import lombok.extern.jackson.Jacksonized;
+
+// PURPOSE : To fulfill the need for the read of CRUD for our terminations repository
+@Getter
+@SuperBuilder(setterPrefix = "with")
+@Jacksonized
+public class GetPendingTerminationsRequest extends CommandRequest {
+ private final String contractId;
+}
diff --git a/shared/src/main/java/com/workup/shared/commands/contracts/responses/EvaluatedMilestoneResponse.java b/shared/src/main/java/com/workup/shared/commands/contracts/responses/EvaluateMilestoneResponse.java
similarity index 80%
rename from shared/src/main/java/com/workup/shared/commands/contracts/responses/EvaluatedMilestoneResponse.java
rename to shared/src/main/java/com/workup/shared/commands/contracts/responses/EvaluateMilestoneResponse.java
index c119e14f..c1319d9d 100644
--- a/shared/src/main/java/com/workup/shared/commands/contracts/responses/EvaluatedMilestoneResponse.java
+++ b/shared/src/main/java/com/workup/shared/commands/contracts/responses/EvaluateMilestoneResponse.java
@@ -8,4 +8,4 @@
@Getter
@SuperBuilder(setterPrefix = "with")
@Jacksonized
-public class EvaluatedMilestoneResponse extends CommandResponse {}
+public class EvaluateMilestoneResponse extends CommandResponse {}
diff --git a/shared/src/main/java/com/workup/shared/commands/contracts/responses/GetContractResponse.java b/shared/src/main/java/com/workup/shared/commands/contracts/responses/GetContractResponse.java
new file mode 100644
index 00000000..6b526bb9
--- /dev/null
+++ b/shared/src/main/java/com/workup/shared/commands/contracts/responses/GetContractResponse.java
@@ -0,0 +1,22 @@
+package com.workup.shared.commands.contracts.responses;
+
+import com.workup.shared.commands.CommandResponse;
+import com.workup.shared.enums.contracts.ContractState;
+import java.util.List;
+import lombok.Getter;
+import lombok.experimental.SuperBuilder;
+import lombok.extern.jackson.Jacksonized;
+
+@Getter
+@SuperBuilder(setterPrefix = "with")
+@Jacksonized
+public class GetContractResponse extends CommandResponse {
+ private final String contractId;
+ private final String jobTitle;
+ private final String jobId;
+ private final String proposalId;
+ private final String freelancerId;
+ private final String clientId;
+ private final List milestonesIds;
+ private final ContractState status;
+}
diff --git a/shared/src/main/java/com/workup/shared/commands/contracts/responses/GetMilestoneResponse.java b/shared/src/main/java/com/workup/shared/commands/contracts/responses/GetMilestoneResponse.java
new file mode 100644
index 00000000..190d4ad6
--- /dev/null
+++ b/shared/src/main/java/com/workup/shared/commands/contracts/responses/GetMilestoneResponse.java
@@ -0,0 +1,22 @@
+package com.workup.shared.commands.contracts.responses;
+
+import com.workup.shared.commands.CommandResponse;
+import com.workup.shared.enums.contracts.MilestoneState;
+import java.util.Date;
+import lombok.Getter;
+import lombok.experimental.SuperBuilder;
+import lombok.extern.jackson.Jacksonized;
+
+@Getter
+@SuperBuilder(setterPrefix = "with")
+@Jacksonized
+public class GetMilestoneResponse extends CommandResponse {
+ private final String milestoneId;
+
+ private final String contractId;
+
+ private final String description;
+ private final Date dueDate;
+ private final double amount;
+ private final MilestoneState status;
+}
diff --git a/shared/src/main/java/com/workup/shared/commands/contracts/responses/GetPendingTerminationsResponse.java b/shared/src/main/java/com/workup/shared/commands/contracts/responses/GetPendingTerminationsResponse.java
new file mode 100644
index 00000000..7f45a4bc
--- /dev/null
+++ b/shared/src/main/java/com/workup/shared/commands/contracts/responses/GetPendingTerminationsResponse.java
@@ -0,0 +1,20 @@
+package com.workup.shared.commands.contracts.responses;
+
+import com.workup.shared.commands.CommandResponse;
+import com.workup.shared.enums.contracts.TerminationRequestStatus;
+import lombok.Getter;
+import lombok.experimental.SuperBuilder;
+import lombok.extern.jackson.Jacksonized;
+
+@Getter
+@SuperBuilder(setterPrefix = "with")
+@Jacksonized
+public class GetPendingTerminationsResponse extends CommandResponse {
+ private final String requestId;
+
+ private final String contractId;
+ private final String requesterId;
+ private final String reason;
+
+ private final TerminationRequestStatus status;
+}