Skip to content

Commit

Permalink
feat(Transaction): implement API for getting all Transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
TonyWu3027 committed Aug 21, 2023
1 parent aac6424 commit 8703925
Show file tree
Hide file tree
Showing 12 changed files with 262 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import uk.ac.ic.doc.blocc.dashboard.transaction.model.ApprovedTempReading;
import uk.ac.ic.doc.blocc.dashboard.transaction.model.Transaction;

@RestController
@RequestMapping(path = "/api/v1/transaction")
Expand All @@ -24,4 +25,9 @@ public List<ApprovedTempReading> getApprovedTransactions(@RequestParam int conta
return transactionService.getApprovedTempReadings(containerNum);
}

@GetMapping("/all")
public List<Transaction> getTransactions(@RequestParam int containerNum) {
return transactionService.getTransactions(containerNum);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package uk.ac.ic.doc.blocc.dashboard.transaction;

import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import uk.ac.ic.doc.blocc.dashboard.transaction.model.ApprovalTransaction;
import uk.ac.ic.doc.blocc.dashboard.transaction.model.CompositeKey;
import uk.ac.ic.doc.blocc.dashboard.transaction.model.Transaction;

@Repository
public interface TransactionRepository
extends JpaRepository<ApprovalTransaction, CompositeKey> {

@Query("SELECT tx FROM Transaction tx WHERE tx.key.containerNum = ?1")
List<Transaction> findAllByContainerNum(int containerNum);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,26 @@
import uk.ac.ic.doc.blocc.dashboard.transaction.model.SensorChaincodeTransaction;
import uk.ac.ic.doc.blocc.dashboard.transaction.model.CompositeKey;
import uk.ac.ic.doc.blocc.dashboard.fabric.model.TemperatureHumidityReading;
import uk.ac.ic.doc.blocc.dashboard.transaction.model.Transaction;

@Service
public class TransactionService {

private final SensorChaincodeTransactionRepository sensorChaincodeTransactionRepository;
private final ApprovalTransactionRepository approvalTransactionRepository;
private final TransactionRepository transactionRepository;

private static final Logger logger =
LoggerFactory.getLogger(TransactionService.class);

@Autowired
public TransactionService(
SensorChaincodeTransactionRepository sensorChaincodeTransactionRepository,
ApprovalTransactionRepository approvalTransactionRepository) {
ApprovalTransactionRepository approvalTransactionRepository,
TransactionRepository transactionRepository) {
this.sensorChaincodeTransactionRepository = sensorChaincodeTransactionRepository;
this.approvalTransactionRepository = approvalTransactionRepository;
this.transactionRepository = transactionRepository;
}

public List<ApprovedTempReading> getApprovedTempReadings(int containerNum) {
Expand Down Expand Up @@ -89,4 +93,8 @@ public void addApprovalTransaction(String txId, int containerNum, String approvi

approvalTransactionRepository.save(approvalTransaction);
}

public List<Transaction> getTransactions(int containerNum) {
return transactionRepository.findAllByContainerNum(containerNum);
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package uk.ac.ic.doc.blocc.dashboard.transaction.model;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import jakarta.persistence.Entity;
import jakarta.persistence.ManyToOne;

@Entity
public class ApprovalTransaction extends Transaction {

@ManyToOne
@JsonSerialize(using = MinimalSensorChaincodeTransactionSerializer.class)
@JsonProperty("approvedTransaction")
private SensorChaincodeTransaction sensorChaincodeTransaction;

public ApprovalTransaction(String txId, int containerNum, String creator, long timestamp,
Expand All @@ -19,10 +23,6 @@ protected ApprovalTransaction() {

}

public SensorChaincodeTransaction getApprovedTransaction() {
return sensorChaincodeTransaction;
}

@Override
public String toString() {
return "Approval " + super.toString();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package uk.ac.ic.doc.blocc.dashboard.transaction.model;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;

public class MinimalApprovalTransactionSerializer extends JsonSerializer<ApprovalTransaction> {

@Override
public void serialize(ApprovalTransaction value, JsonGenerator gen,
SerializerProvider serializers) throws IOException {
gen.writeStartObject();
gen.writeStringField("txId", value.getTxId());
gen.writeStringField("creator", value.getCreator());
gen.writeNumberField("createdTimestamp", value.getCreatedTimestamp());
gen.writeEndObject();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package uk.ac.ic.doc.blocc.dashboard.transaction.model;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;

public class MinimalSensorChaincodeTransactionSerializer extends
JsonSerializer<SensorChaincodeTransaction> {

@Override
public void serialize(SensorChaincodeTransaction transaction, JsonGenerator gen,
SerializerProvider serializers) throws IOException {
gen.writeStartObject();
gen.writeStringField("txId", transaction.getTxId());
gen.writeStringField("creator", transaction.getCreator());
gen.writeNumberField("createdTimestamp", transaction.getCreatedTimestamp());
gen.writeObjectField("reading", transaction.getReading());
gen.writeEndObject();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package uk.ac.ic.doc.blocc.dashboard.transaction.model;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import jakarta.persistence.Entity;
import jakarta.persistence.OneToMany;
import java.util.ArrayList;
Expand All @@ -10,6 +12,7 @@
public class SensorChaincodeTransaction extends Transaction {

@OneToMany(mappedBy = "sensorChaincodeTransaction")
@JsonSerialize(contentUsing = MinimalApprovalTransactionSerializer.class)
private List<ApprovalTransaction> approvals = new ArrayList<>();
private TemperatureHumidityReading reading;

Expand Down Expand Up @@ -37,7 +40,9 @@ public String toString() {
return "Sensor Chaincode " + super.toString();
}

@JsonIgnore
public int getApprovalCount() {
return approvals.size();
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package uk.ac.ic.doc.blocc.dashboard.transaction.model;

import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Entity;
import jakarta.persistence.Inheritance;
Expand All @@ -15,6 +16,7 @@ public CompositeKey getKey() {
}

@EmbeddedId
@JsonIgnore
protected CompositeKey key;
protected String creator;
protected long createdTimestamp;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import uk.ac.ic.doc.blocc.dashboard.fabric.model.TemperatureHumidityReading;
import uk.ac.ic.doc.blocc.dashboard.transaction.model.ApprovalTransaction;
import uk.ac.ic.doc.blocc.dashboard.transaction.model.ApprovedTempReading;
import uk.ac.ic.doc.blocc.dashboard.transaction.model.SensorChaincodeTransaction;
import uk.ac.ic.doc.blocc.dashboard.transaction.model.Transaction;

@WebMvcTest(TransactionController.class)
class TransactionControllerTest {
Expand Down Expand Up @@ -53,4 +57,44 @@ public void getEmptyListIfApprovedTransactionsNotExist() throws Exception {
.andExpect(MockMvcResultMatchers.jsonPath("$.size()").value(0));
}

@Test
public void getAllExistingTransactionsForSpecifiedContainer() throws Exception {
int containerNum = 1;

// Given
SensorChaincodeTransaction tx1 = new SensorChaincodeTransaction(
"tx123",
1,
"Container5MSP",
100L,
new TemperatureHumidityReading(25, 0.3F, 100L));

SensorChaincodeTransaction tx2 = new SensorChaincodeTransaction(
"tx456",
1,
"Container5MSP",
103L,
new TemperatureHumidityReading(30, 0.2F, 103L));

SensorChaincodeTransaction tx3 = new SensorChaincodeTransaction(
"tx1299",
1,
"Container5MSP",
100L,
new TemperatureHumidityReading(22, 0.3F, 100L));

ApprovalTransaction approval1 = new ApprovalTransaction(
"app1", 1, "Container6MSP", 101L, tx1);
ApprovalTransaction approval2 = new ApprovalTransaction(
"app2", 1, "Container7MSP", 102L, tx1);

List<Transaction> transactions = List.of(tx1, tx2, tx3, approval1, approval2);

when(transactionService.getTransactions(containerNum)).thenReturn(transactions);

mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/transaction/all")
.param("containerNum", String.valueOf(containerNum)))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.size()").value(5));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package uk.ac.ic.doc.blocc.dashboard.transaction;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.PostgreSQLContainer;
import uk.ac.ic.doc.blocc.dashboard.fabric.model.TemperatureHumidityReading;
import uk.ac.ic.doc.blocc.dashboard.transaction.model.ApprovalTransaction;
import uk.ac.ic.doc.blocc.dashboard.transaction.model.SensorChaincodeTransaction;
import uk.ac.ic.doc.blocc.dashboard.transaction.model.Transaction;

@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class TransactionRepositoryTest {

static final PostgreSQLContainer<?> postgres =
new PostgreSQLContainer<>("postgres:latest");

static {
postgres.start();
}

@DynamicPropertySource
static void properties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
}

@Autowired
private TestEntityManager entityManager;

@Autowired
private TransactionRepository repository;

@Test
void findAllByContainerNum() {
// Given
SensorChaincodeTransaction tx1 = new SensorChaincodeTransaction(
"tx123",
1,
"Container5MSP",
100L,
new TemperatureHumidityReading(25, 0.3F, 100L));

SensorChaincodeTransaction tx2 = new SensorChaincodeTransaction(
"tx456",
3,
"Container5MSP",
103L,
new TemperatureHumidityReading(30, 0.2F, 103L));

SensorChaincodeTransaction tx3 = new SensorChaincodeTransaction(
"tx1299",
1,
"Container5MSP",
100L,
new TemperatureHumidityReading(22, 0.3F, 100L));

ApprovalTransaction approval1 = new ApprovalTransaction(
"app1", 1, "Container6MSP", 101L, tx1);
ApprovalTransaction approval2 = new ApprovalTransaction(
"app2", 1, "Container7MSP", 102L, tx1);
ApprovalTransaction approval3 = new ApprovalTransaction(
"app3", 3, "Container9MSP", 102L, tx2);
ApprovalTransaction approval4 = new ApprovalTransaction(
"app4", 1, "Container7MSP", 102L, tx3);

entityManager.persist(tx1);
entityManager.persist(tx2);
entityManager.persist(tx3);
entityManager.persist(approval1);
entityManager.persist(approval2);
entityManager.persist(approval3);
entityManager.persist(approval4);
entityManager.flush();

// When
List<Transaction> found = repository.findAllByContainerNum(1);

// Then
assertThat(found).hasSize(5).contains(tx1, tx3, approval1, approval2, approval4);
assertThat(found).doesNotContain(tx2, approval3);
}
}
Loading

0 comments on commit 8703925

Please sign in to comment.