From a23c435d67b5ca1765048c3203bc195af8801e2a Mon Sep 17 00:00:00 2001 From: Petros Kostenidis Date: Tue, 7 Oct 2025 21:20:27 +0200 Subject: [PATCH] Salvatore's Exercise - Complete --- .../ExerciseCheckSolutionsApplication.java | 13 + .../controller/TransactionController.java | 63 +++++ .../demo/DataLoader.java | 93 +++++++ .../enums/AccountType.java | 11 + .../enums/Attribute.java | 7 + .../enums/Currency.java | 14 + .../enums/TransactionType.java | 12 + .../model/Transaction.java | 244 ++++++++++++++++++ .../repository/TransactionRepository.java | 22 ++ .../service/TransactionService.java | 95 +++++++ src/main/resources/application.properties | 13 + ...xerciseCheckSolutionsApplicationTests.java | 13 + 12 files changed, 600 insertions(+) create mode 100644 src/main/java/com/ironhack/exercisechecksolutions/ExerciseCheckSolutionsApplication.java create mode 100644 src/main/java/com/ironhack/exercisechecksolutions/controller/TransactionController.java create mode 100644 src/main/java/com/ironhack/exercisechecksolutions/demo/DataLoader.java create mode 100644 src/main/java/com/ironhack/exercisechecksolutions/enums/AccountType.java create mode 100644 src/main/java/com/ironhack/exercisechecksolutions/enums/Attribute.java create mode 100644 src/main/java/com/ironhack/exercisechecksolutions/enums/Currency.java create mode 100644 src/main/java/com/ironhack/exercisechecksolutions/enums/TransactionType.java create mode 100644 src/main/java/com/ironhack/exercisechecksolutions/model/Transaction.java create mode 100644 src/main/java/com/ironhack/exercisechecksolutions/repository/TransactionRepository.java create mode 100644 src/main/java/com/ironhack/exercisechecksolutions/service/TransactionService.java create mode 100644 src/main/resources/application.properties create mode 100644 src/test/java/com/ironhack/exercisechecksolutions/ExerciseCheckSolutionsApplicationTests.java diff --git a/src/main/java/com/ironhack/exercisechecksolutions/ExerciseCheckSolutionsApplication.java b/src/main/java/com/ironhack/exercisechecksolutions/ExerciseCheckSolutionsApplication.java new file mode 100644 index 0000000..42771cb --- /dev/null +++ b/src/main/java/com/ironhack/exercisechecksolutions/ExerciseCheckSolutionsApplication.java @@ -0,0 +1,13 @@ +package com.ironhack.exercisechecksolutions; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ExerciseCheckSolutionsApplication { + + public static void main(String[] args) { + SpringApplication.run(ExerciseCheckSolutionsApplication.class, args); + } + +} diff --git a/src/main/java/com/ironhack/exercisechecksolutions/controller/TransactionController.java b/src/main/java/com/ironhack/exercisechecksolutions/controller/TransactionController.java new file mode 100644 index 0000000..18c2a85 --- /dev/null +++ b/src/main/java/com/ironhack/exercisechecksolutions/controller/TransactionController.java @@ -0,0 +1,63 @@ +package com.ironhack.exercisechecksolutions.controller; + +import com.ironhack.exercisechecksolutions.enums.Attribute; +import com.ironhack.exercisechecksolutions.enums.Currency; +import com.ironhack.exercisechecksolutions.model.Transaction; +import com.ironhack.exercisechecksolutions.service.TransactionService; +import jakarta.websocket.server.PathParam; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.UUID; + +@RestController +@RequestMapping("/transactions") +public class TransactionController { + + private final TransactionService transactionService; + + public TransactionController(TransactionService transactionService){ + this.transactionService = transactionService; + } + + @PostMapping + public Transaction create(@RequestBody Transaction transaction){ + return transactionService.create(transaction); + } + + @GetMapping("/all") + public List getAllTransactions(){ + return transactionService.getAllTransactions(); + } + + @PutMapping("/{id}") + public Transaction update(@PathVariable UUID id,@RequestBody Transaction transaction){ + return transactionService.updateTransaction(id, transaction); + } + + @DeleteMapping("/{id}") + public void deleteTransaction(@PathVariable UUID id) { + transactionService.deleteTransaction(id); + } + + + @GetMapping("/attribute/{attribute}") + public List getTransactionsByAttribute(@PathVariable Attribute attribute){ + return transactionService.findByAttribute(attribute); + } + + @GetMapping("/currency/{currency}") + public List getTransactionsByCurrency(@PathVariable Currency currency){ + return transactionService.findByCurrency(currency); + } + + @GetMapping("/accountHolder/{accountHolder}") + public List getTransactionsByAccountHolder(@PathVariable String accountHolder){ + return transactionService.findByAccountHolderName(accountHolder); + } + + +} + + + diff --git a/src/main/java/com/ironhack/exercisechecksolutions/demo/DataLoader.java b/src/main/java/com/ironhack/exercisechecksolutions/demo/DataLoader.java new file mode 100644 index 0000000..2c8efa8 --- /dev/null +++ b/src/main/java/com/ironhack/exercisechecksolutions/demo/DataLoader.java @@ -0,0 +1,93 @@ +package com.ironhack.exercisechecksolutions.demo; + +import com.ironhack.exercisechecksolutions.enums.AccountType; +import com.ironhack.exercisechecksolutions.enums.Attribute; +import com.ironhack.exercisechecksolutions.enums.Currency; +import com.ironhack.exercisechecksolutions.enums.TransactionType; +import com.ironhack.exercisechecksolutions.model.Transaction; +import com.ironhack.exercisechecksolutions.service.TransactionService; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalTime; + +@Component +public class DataLoader implements CommandLineRunner { + + private final TransactionService transactionService; + + public DataLoader(TransactionService transactionService) { + this.transactionService = transactionService; + } + + @Override + public void run(String... args) throws Exception { + System.out.println("Loading initial data..."); + if (!transactionService.getAllTransactions().isEmpty()) { + System.out.println("Data already loaded, skipping..."); + return; + } + + var transaction1 = new Transaction("Petros Kostenidis", + "PK_JPM_BANK_3", + AccountType.CHECKING_ACCOUNT, + "US00 0010 4657 6548 9990", + LocalTime.of(15,50,15), + LocalDate.of(2025,9,14), + LocalDate.of(2025,9,14), + TransactionType.DEBIT, + Currency.USD, + "CAFETERIALO MARKO RODA 6767_G4DPFDM5TG", + BigDecimal.valueOf(17.23), + Attribute.Expense, + "Recreation", + "Coffee", + "Fredo Espresso,Medium Sugar"); + transactionService.create(transaction1); + System.out.println("Data loaded!"); + + var transaction2 = new Transaction("Petros Kostenidis", + "PK_JPM_BANK_2", + AccountType.CHECKING_ACCOUNT, + "US200 0010 4657 6548 9990", + LocalTime.of(19,50,15), + LocalDate.of(2025,9,4), + LocalDate.of(2025,9,5), + TransactionType.DEBIT, + Currency.USD, + "ELECTROPLANET Laptop 965DC85D", + BigDecimal.valueOf(800.20), + Attribute.Expense, + "Electronic Device", + "Laptop", + "Lenovo 656hx"); + transactionService.create(transaction1); + System.out.println("Data loaded!"); + + var transaction3 = new Transaction("Petros Kostenidis", + "PK_JPM_BANK_3", + AccountType.CHECKING_ACCOUNT, + "US00 0010 4657 6548 9990", + LocalTime.of(17,50,02), + LocalDate.of(2025,9,02), + LocalDate.of(2025,9,02), + TransactionType.DEBIT, + Currency.USD, + "FURNITURAKIA 858585 ASDL", + BigDecimal.valueOf(17.23), + Attribute.Expense, + "Household", + "Furniture", + "Sofa"); + + transactionService.create(transaction1); + transactionService.create(transaction2); + transactionService.create(transaction3); + System.out.println("Data loaded!"); + + + + } +} \ No newline at end of file diff --git a/src/main/java/com/ironhack/exercisechecksolutions/enums/AccountType.java b/src/main/java/com/ironhack/exercisechecksolutions/enums/AccountType.java new file mode 100644 index 0000000..3d08fb0 --- /dev/null +++ b/src/main/java/com/ironhack/exercisechecksolutions/enums/AccountType.java @@ -0,0 +1,11 @@ +package com.ironhack.exercisechecksolutions.enums; + +public enum AccountType { + CHECKING_ACCOUNT, + DEPOSIT_ACCOUNT, + SAVINGS_ACCOUNT, + EMERGENCY_FUND_ACCOUNT, + CREDIT_CARD_ACCOUNT, + INVESTMENT_ACCOUNT, + CRYPTO_ACCOUNT +} diff --git a/src/main/java/com/ironhack/exercisechecksolutions/enums/Attribute.java b/src/main/java/com/ironhack/exercisechecksolutions/enums/Attribute.java new file mode 100644 index 0000000..cecaca2 --- /dev/null +++ b/src/main/java/com/ironhack/exercisechecksolutions/enums/Attribute.java @@ -0,0 +1,7 @@ +package com.ironhack.exercisechecksolutions.enums; + +public enum Attribute { + Income, + Expense, + Zero_Value_Transaction +} diff --git a/src/main/java/com/ironhack/exercisechecksolutions/enums/Currency.java b/src/main/java/com/ironhack/exercisechecksolutions/enums/Currency.java new file mode 100644 index 0000000..3c05f6c --- /dev/null +++ b/src/main/java/com/ironhack/exercisechecksolutions/enums/Currency.java @@ -0,0 +1,14 @@ +package com.ironhack.exercisechecksolutions.enums; + +public enum Currency { + USD, + EUR, + GBP, + CHF, + CNY, + JPY, + AUD, + CAD, + HKD, + NZD, +} diff --git a/src/main/java/com/ironhack/exercisechecksolutions/enums/TransactionType.java b/src/main/java/com/ironhack/exercisechecksolutions/enums/TransactionType.java new file mode 100644 index 0000000..666eeba --- /dev/null +++ b/src/main/java/com/ironhack/exercisechecksolutions/enums/TransactionType.java @@ -0,0 +1,12 @@ +package com.ironhack.exercisechecksolutions.enums; + +public enum TransactionType { + DEBIT, + CREDIT, + TRANSFER, + CASH_DEPOSIT, + WITHDRAWAL, + INTEREST, + CHARGES, + TAXES +} diff --git a/src/main/java/com/ironhack/exercisechecksolutions/model/Transaction.java b/src/main/java/com/ironhack/exercisechecksolutions/model/Transaction.java new file mode 100644 index 0000000..fbe1649 --- /dev/null +++ b/src/main/java/com/ironhack/exercisechecksolutions/model/Transaction.java @@ -0,0 +1,244 @@ +package com.ironhack.exercisechecksolutions.model; + +import com.ironhack.exercisechecksolutions.enums.AccountType; +import com.ironhack.exercisechecksolutions.enums.Attribute; +import com.ironhack.exercisechecksolutions.enums.Currency; +import com.ironhack.exercisechecksolutions.enums.TransactionType; +import jakarta.persistence.*; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.UUID; + +@Entity +@Table(name = "Statement") +public class Transaction { + + @Id + @GeneratedValue(strategy = GenerationType.UUID) + private UUID id; + + @Column(name = "Account Holder", nullable = false, length = 50) + private String accountHolder; + + @Column(name = "Account Name", nullable = false, length = 50) + private String accountName; + + @Enumerated(EnumType.STRING) + @Column(name = "Account Type") + private AccountType accountType; + + @Column(name = "Account IBAN", nullable = false, length = 50) + private String accountIBAN; + + @Column(name = "Value Time", nullable = false, length = 8) + private LocalTime valueTime; + + @Column(name = "Value Date", nullable = false, length = 10) + private LocalDate valueDate; + + @Column(name = "Booking Date", nullable = false, length = 10) + private LocalDate bookingDate; + + @Enumerated(EnumType.STRING) + @Column(name = "Transaction Type") + private TransactionType transactionType; + + @Enumerated(EnumType.STRING) + @Column(name = "Currency") + private Currency currency; + + @Column(name = "Booking Text", nullable = false, length = 160) + private String bookingText; + + @Column(name = "Amount") + private BigDecimal amount; + + @Enumerated(EnumType.STRING) + @Column(name = "Attribute") + private Attribute attribute; + + @Column(name = "Category", length = 50) + private String category; + @Column(name = "Sub Category", length = 50) + private String subCategory; + + @Column(name = "Description", length = 50) + private String description; + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public String getAccountHolder() { + return accountHolder; + } + + public void setAccountHolder(String accountHolder) { + this.accountHolder = accountHolder; + } + + public String getAccountName() { + return accountName; + } + + public void setAccountName(String accountName) { + this.accountName = accountName; + } + + public AccountType getAccountType() { + return accountType; + } + + public void setAccountType(AccountType accountType) { + this.accountType = accountType; + } + + public String getAccountIBAN() { + return accountIBAN; + } + + public void setAccountIBAN(String accountIBAN) { + this.accountIBAN = accountIBAN; + } + + public LocalTime getValueTime() { + return valueTime; + } + + public void setValueTime(LocalTime valueTime) { + this.valueTime = valueTime; + } + + public LocalDate getValueDate() { + return valueDate; + } + + public void setValueDate(LocalDate valueDate) { + this.valueDate = valueDate; + } + + public LocalDate getBookingDate() { + return bookingDate; + } + + public void setBookingDate(LocalDate bookingDate) { + this.bookingDate = bookingDate; + } + + public TransactionType getTransactionType() { + return transactionType; + } + + public void setTransactionType(TransactionType transactionType) { + this.transactionType = transactionType; + } + + public Currency getCurrency() { + return currency; + } + + public void setCurrency(Currency currency) { + this.currency = currency; + } + + public String getBookingText() { + return bookingText; + } + + public void setBookingText(String bookingText) { + this.bookingText = bookingText; + } + + public BigDecimal getAmount() { + return amount; + } + + public void setAmount(BigDecimal amount) { + this.amount = amount; + } + + public Attribute getAttribute() { + return attribute; + } + + public void setAttribute(Attribute attribute) { + this.attribute = attribute; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + public String getSubCategory() { + return subCategory; + } + + public void setSubCategory(String subCategory) { + this.subCategory = subCategory; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Transaction(String accountHolder, String accountName, AccountType accountType, String accountIBAN, LocalTime valueTime, LocalDate valueDate, LocalDate bookingDate, TransactionType transactionType, Currency currency, String bookingText, BigDecimal amount, Attribute attribute, String category, String subCategory, String description) { + this.accountHolder = accountHolder;//"Petros Kostenidis" + this.accountName = accountName;//"PK_JPM_BANK_3" + this.accountType = accountType;//"Checking Account" + this.accountIBAN = accountIBAN;//"US00 0010 4657 6548 9990" + this.valueTime = valueTime;//15:50:15 + this.valueDate = valueDate;//14/09/2025 + this.bookingDate = bookingDate;//14/09/2025 + this.transactionType = transactionType;//"Debit" + this.currency = currency;//"USD" + this.bookingText = bookingText;//"CAFETERIALO MARKO RODA 6767_G4DPFDM5TG" + this.amount = amount;//17.23 + this.attribute = attribute;//"Expense" + this.category = category;//"Recreation" + this.subCategory = subCategory;//"Coffee" + this.description = description;//"Fredo Espresso, Medium Sugar" + } + + public Transaction() { + } + + @Override + public String toString() { + return "Transaction{" + + "id=" + id + + ", Account Holder='" + accountHolder + '\'' + + ", Account Name='" + accountName + '\'' + + ", Account Type='" + accountType + '\'' + + ", Account IBAN=" + accountIBAN + + ", Value Time=" + valueTime + + ", Value Date=" + valueDate + + ", Booking Date=" + bookingDate + + ", Transaction Type=" + transactionType + + ", Currency=" + currency + + ", Booking Text=" + bookingText + + ", Amount=" + amount + + ", Attribute=" + attribute + + ", Category=" + category + + ", Sub Category=" + subCategory + + ", Description=" + description + + '}'; + } + + + +} + diff --git a/src/main/java/com/ironhack/exercisechecksolutions/repository/TransactionRepository.java b/src/main/java/com/ironhack/exercisechecksolutions/repository/TransactionRepository.java new file mode 100644 index 0000000..ed5f337 --- /dev/null +++ b/src/main/java/com/ironhack/exercisechecksolutions/repository/TransactionRepository.java @@ -0,0 +1,22 @@ +package com.ironhack.exercisechecksolutions.repository; + +import com.ironhack.exercisechecksolutions.enums.Attribute; +import com.ironhack.exercisechecksolutions.enums.Currency; +import com.ironhack.exercisechecksolutions.model.Transaction; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.UUID; + +@Repository +public interface TransactionRepository extends JpaRepository { + + List findByAttribute(Attribute attribute); + + List findByCurrency(Currency currency); + + @Query("SELECT t FROM Transaction t WHERE t.accountHolder = ?1") + List findByAccountHolderName(String accountHolder); +} diff --git a/src/main/java/com/ironhack/exercisechecksolutions/service/TransactionService.java b/src/main/java/com/ironhack/exercisechecksolutions/service/TransactionService.java new file mode 100644 index 0000000..72b481b --- /dev/null +++ b/src/main/java/com/ironhack/exercisechecksolutions/service/TransactionService.java @@ -0,0 +1,95 @@ +package com.ironhack.exercisechecksolutions.service; + +import com.ironhack.exercisechecksolutions.enums.Attribute; +import com.ironhack.exercisechecksolutions.enums.Currency; +import com.ironhack.exercisechecksolutions.model.Transaction; +import com.ironhack.exercisechecksolutions.repository.TransactionRepository; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.UUID; + +@Service +public class TransactionService { + + private final TransactionRepository transactionRepository; + + public TransactionService(TransactionRepository transactionRepository){ + this.transactionRepository = transactionRepository; + } + + // CRUD - SQL - HTTP + //------------------------ + // Create = Insert = POST + // Read = Select = GET + // Update = Update = PUT/PATCH + // Delete = Delete = DELETE + + // Create + public Transaction create(Transaction transaction){ + return transactionRepository.save(transaction); + } + + // Read + public List getAllTransactions(){ + return transactionRepository.findAll(); + } + + // Update + public Transaction updateTransaction(UUID id,Transaction transaction) { + Transaction existingTransaction = transactionRepository.findById(id) + .orElseThrow(() -> new RuntimeException("Transaction not found with id: " + id)); + existingTransaction.setAccountHolder(transaction.getAccountHolder()); + existingTransaction.setAccountName(transaction.getAccountName()); + existingTransaction.setAccountType(transaction.getAccountType()); + existingTransaction.setAccountIBAN(transaction.getAccountIBAN()); + existingTransaction.setValueTime(transaction.getValueTime()); + existingTransaction.setValueDate(transaction.getValueDate()); + existingTransaction.setBookingDate(transaction.getBookingDate()); + existingTransaction.setTransactionType(transaction.getTransactionType()); + existingTransaction.setCurrency(transaction.getCurrency()); + existingTransaction.setBookingText(transaction.getBookingText()); + existingTransaction.setAmount(transaction.getAmount()); + existingTransaction.setAttribute(transaction.getAttribute()); + existingTransaction.setCategory(transaction.getCategory()); + existingTransaction.setSubCategory(transaction.getSubCategory()); + existingTransaction.setDescription(transaction.getDescription()); + return transactionRepository.save(existingTransaction); + } + + //Delete + public void deleteTransaction(UUID id){ + Transaction existingTransaction = transactionRepository.findById(id) + .orElseThrow(() -> new RuntimeException("Transaction not found with id: " + id)); + transactionRepository.delete(existingTransaction); + } + + public List findByAttribute(Attribute attribute) { + return transactionRepository.findByAttribute(attribute); + } + + public List findByCurrency(Currency currency) { + return transactionRepository.findByCurrency(currency); + } + + public List findByAccountHolderName(String accountHolder) { + return transactionRepository.findByAccountHolderName(accountHolder); + } + + +} + + + + + + + + + + + + + + + diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..e610cb8 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,13 @@ +spring.application.name=exercise-check-solutions + + +# Connection configuration +spring.datasource.url=jdbc:mysql://localhost:3306/exercise_salva +spring.datasource.username=root +spring.datasource.password=8520654GX_/.33cRmpet +# JPA properties +spring.jpa.hibernate.ddl-auto=create +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect +# Server port (optional) +spring.server.port=8080 \ No newline at end of file diff --git a/src/test/java/com/ironhack/exercisechecksolutions/ExerciseCheckSolutionsApplicationTests.java b/src/test/java/com/ironhack/exercisechecksolutions/ExerciseCheckSolutionsApplicationTests.java new file mode 100644 index 0000000..48ae465 --- /dev/null +++ b/src/test/java/com/ironhack/exercisechecksolutions/ExerciseCheckSolutionsApplicationTests.java @@ -0,0 +1,13 @@ +package com.ironhack.exercisechecksolutions; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ExerciseCheckSolutionsApplicationTests { + + @Test + void contextLoads() { + } + +}