Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scrum 46 add portfolio details for user in user service #42

Merged
merged 12 commits into from
Jul 31, 2024
6 changes: 3 additions & 3 deletions .github/workflows/users-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ jobs:

- name: Run tests
env:
DB_URL: jdbc:postgresql://postgres:5432/usermanagement
DB_URL: jdbc:postgresql://localhost:5432/usermanagement
DB_USERNAME: postgres
DB_PASSWORD: postgres
JWT_SECRET: ${{ github.sha }}
run: bash ./gradlew :UserManagement:test -Dspring.profiles.active=test
JWT_SECRET: secret
run: bash ./gradlew :UserManagement:test

- name: Build with Gradle
run: bash ./gradlew :UserManagement:build
3 changes: 3 additions & 0 deletions UserManagement/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,7 @@ dependencies {

tasks.withType<Test> {
useJUnitPlatform()
testLogging {
events("passed", "skipped", "failed")
}
}
6 changes: 6 additions & 0 deletions UserManagement/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#Tue Jul 30 11:08:16 GMT 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.joe.trading.user_management.entities;

import jakarta.persistence.*;
import lombok.*;
import org.hibernate.annotations.CreationTimestamp;

import java.time.LocalDateTime;

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@ToString
public class Portfolio {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "portfolio_name", nullable = false)
private String name;

@ManyToOne
@JoinColumn(name = "user_id", nullable = false)
private User user;

@Column(name = "created_at", nullable = false)
@CreationTimestamp
private LocalDateTime createdAt;

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.joe.trading.user_management.entities;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import jakarta.persistence.*;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import org.springframework.security.core.GrantedAuthority;
Expand All @@ -12,13 +14,6 @@

import com.joe.trading.user_management.enums.AccountType;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.validation.constraints.Email;
import lombok.AllArgsConstructor;
import lombok.Getter;
Expand Down Expand Up @@ -58,7 +53,10 @@ public class User implements UserDetails {
private LocalDateTime updatedAt;

@Column(name = "pending_delete", nullable = false, columnDefinition = "boolean default false")
private Boolean pendingDelete;
private Boolean pendingDelete = false;

@OneToMany(mappedBy = "user", cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
private transient List<Portfolio> portfolios = new ArrayList<>();

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Expand Down Expand Up @@ -94,4 +92,19 @@ public boolean isCredentialsNonExpired() {
public boolean isEnabled() {
return true;
}

@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", passwordHash='" + passwordHash + '\'' +
", accountType=" + accountType +
", createdAt=" + createdAt +
", updatedAt=" + updatedAt +
", pendingDelete=" + pendingDelete +
", portfolios=" + portfolios +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.joe.trading.user_management.repository;

import com.joe.trading.user_management.entities.Portfolio;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface PortfolioRepository extends JpaRepository<Portfolio, Long> {

Optional<Portfolio> findByUserId(Long userId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ public interface UserService {
User getUserById(Long userId) throws ResourceNotFoundException;
List<User> getAllUsers();
User updateUser(Long userId, UpdateUserDto updatedUser) throws ResourceNotFoundException;

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import java.util.List;

import com.joe.trading.user_management.entities.Portfolio;
import com.joe.trading.user_management.repository.PortfolioRepository;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

Expand All @@ -14,11 +16,13 @@
import com.joe.trading.user_management.services.UserService;

import lombok.AllArgsConstructor;
import org.springframework.transaction.annotation.Transactional;

@Service
@AllArgsConstructor
public class UserServiceImpl implements UserService {
private UserRepository userRepository;
private PortfolioRepository portfolioRepository;
private PasswordEncoder passwordEncoder;

public User getUserById(Long userId) throws ResourceNotFoundException {
Expand Down Expand Up @@ -65,4 +69,5 @@ public User updateUser(Long userId, UpdateUserDto updatedUser) throws ResourceNo

return existingUser;
}

}
12 changes: 12 additions & 0 deletions UserManagement/src/main/resources/application-test.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# In-memory H2 database configuration
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=in_memory
spring.datasource.password=in_memory
spring.sql.init.platform=h2
spring.h2.console.enabled=true

# Hibernate settings
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
5 changes: 2 additions & 3 deletions UserManagement/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ spring.application.name=UserManagement
spring.datasource.url=${DB_URL}
spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWORD}
#spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.driver-class-name=org.postgresql.Driver

spring.jpa.hibernate.ddl-auto=update

springdoc.swagger-ui.path=/swagger-ui.html

security.jwt.secret-key=${JWT_SECRET}
# 1h in millisecond
security.jwt.expiration-time=3600000

# Enable H2 Console for testing purposes (optional)
spring.h2.console.enabled=true
#spring.h2.console.enabled=true
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
package com.joe.trading.user_management;

import com.joe.trading.user_management.entities.Portfolio;
import com.joe.trading.user_management.entities.User;
import com.joe.trading.user_management.repository.PortfolioRepository;
import com.joe.trading.user_management.repository.UserRepository;
import com.joe.trading.user_management.services.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;



@SpringBootTest
class UserManagementApplicationTests {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,113 @@
package com.joe.trading.user_management.entites;

import com.joe.trading.user_management.entities.User;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;

import java.util.List;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.transaction.annotation.Transactional;

import static org.junit.jupiter.api.Assertions.*;
import com.joe.trading.user_management.entities.Portfolio;
import com.joe.trading.user_management.entities.User;
import com.joe.trading.user_management.enums.AccountType;
import com.joe.trading.user_management.repository.PortfolioRepository;
import com.joe.trading.user_management.repository.UserRepository;

@DataJpaTest
public class UserTest {

@Autowired
private UserRepository userRepository;

@Autowired
private PortfolioRepository portfolioRepository;

@Test
void testCreateUser(){
@Transactional
void testAddUserPortfolio() {
User user = new User();
user.setId(1L);
user.setName("testuser");
user.setEmail("test@example.com");
user.setPasswordHash("password");
user.setAccountType(AccountType.USER);
user.setPendingDelete(false);

Portfolio p1 = new Portfolio();
p1.setName("T stocks");
p1.setUser(user);

user.setPortfolios(List.of(p1));

userRepository.save(user);

assertEquals(1L,user.getId());
user = userRepository.getReferenceById(user.getId());

assertNotNull(user.getPortfolios());
assertEquals(1, user.getPortfolios().size());
assertEquals(p1.getUser().getId(), user.getId());
}

@Test
@Transactional
void testDeleteUserWithPortfolio() {
User user = new User();
user.setName("testuser");
user.setEmail("test@email.com");
user.setPasswordHash("password");
user.setAccountType(AccountType.USER);
user.setPendingDelete(false);

Portfolio p1 = new Portfolio();
p1.setName("T stocks");
p1.setUser(user);

user.setPortfolios(List.of(p1));

userRepository.save(user);
portfolioRepository.save(p1);

assertEquals(1, userRepository.count());
assertEquals(1, portfolioRepository.count());

assertThrows(DataIntegrityViolationException.class, () -> {
userRepository.delete(user);
userRepository.flush();
});
}

@Test
@Transactional
void testDeleteUserWithoutPortfolio() {
User user = new User();
user.setName("testuser");
user.setEmail("test@email.com");
user.setPasswordHash("password");
user.setAccountType(AccountType.USER);
user.setPendingDelete(false);
userRepository.save(user);

Portfolio p1 = new Portfolio();
p1.setName("T stocks");
p1.setUser(user);

user.setPortfolios(List.of(p1));

portfolioRepository.save(p1);

assertEquals(1, portfolioRepository.count());
assertEquals(1, userRepository.count());

portfolioRepository.delete(p1);
portfolioRepository.flush();

assertEquals(0, portfolioRepository.count()); // delete portfolio

userRepository.delete(user);
assertEquals(0, userRepository.count());
}
}