Skip to content

Commit

Permalink
Merge pull request #218 from Invivoo/develop
Browse files Browse the repository at this point in the history
#199 update user from lynx + use email for authentication and to find activity owner
  • Loading branch information
Nicolas ERNY authored Apr 13, 2023
2 parents 224362d + 4f96cc5 commit 527a43a
Show file tree
Hide file tree
Showing 34 changed files with 967 additions and 131 deletions.
3 changes: 2 additions & 1 deletion ViV-Wallet-api/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ ADD target/ViV-Wallet-api-0.0.1-SNAPSHOT.jar ViV-Wallet-api-0.0.1-SNAPSHOT.jar

ENV X4BAuthPublicKeyUrl="" \
LynxApiUrl="" \
LynxUserApiUrl="" \
ApiKey="" \
SqlServerUrl="SQL_SERVER_URL" \
SqlServerUsername="SQL_SERVER_USERNAME" \
Expand All @@ -14,4 +15,4 @@ ENV X4BAuthPublicKeyUrl="" \

EXPOSE 8080

CMD java -jar ViV-Wallet-api-0.0.1-SNAPSHOT.jar --app.url=$VivWalletUrl --x4b.auth.publicKeyUrl=$X4BAuthPublicKeyUrl --lynx.vivApiUrl=$LynxApiUrl --api.key=$ApiKey --spring.datasource.url=$SqlServerUrl --spring.datasource.username=$SqlServerUsername --spring.datasource.password=$SqlServerPassword --spring.profiles.active=sqlServer
CMD java -jar ViV-Wallet-api-0.0.1-SNAPSHOT.jar --app.url=$VivWalletUrl --x4b.auth.publicKeyUrl=$X4BAuthPublicKeyUrl --lynx.vivApiUrl=$LynxApiUrl --lynx.userApiUrl=$LynxUserApiUrl --api.key=$ApiKey --spring.datasource.url=$SqlServerUrl --spring.datasource.username=$SqlServerUsername --spring.datasource.password=$SqlServerPassword --spring.profiles.active=sqlServer
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import javax.transaction.Transactional;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
Expand All @@ -18,6 +19,7 @@
@Service
public class ActionService {

public static final LocalDateTime MINIMUM_SART_VALUE_DATE_VALID_FOR_JPA_QUERY = LocalDateTime.of(2000, Month.JANUARY, 1, 0, 0);
private final ActionRepository actionRepository;
private final LynxConnector lynxConnector;

Expand All @@ -31,8 +33,7 @@ public List<Action> findAllByOrderByDateDesc() {
}

public List<Action> findAllByAchieverOrderByDateDesc(User achiever) {
LocalDateTime startValueDate = Optional.ofNullable(achiever.getVivInitialBalanceDate()).orElse(
LocalDateTime.MIN);
LocalDateTime startValueDate = Optional.ofNullable(achiever.getVivInitialBalanceDate()).orElse(MINIMUM_SART_VALUE_DATE_VALID_FOR_JPA_QUERY);
ArrayList<Action> actions = new ArrayList<>(actionRepository.findAllByAchieverAndValueDateAfter(achiever, startValueDate));
getActionForInitialBalance(achiever).ifPresent(actions::add);
actions.sort(Comparator.comparing(Action::getDate).reversed());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,22 @@ public enum Expertise {
PROGRAMMATION_C_PLUS_PLUS("Programmation C++"),
PROGRAMMATION_PYTHON("Programmation Python"),
FRONT_END("Front-End"),
MACHINE_LEARNING("Machine Learning"),
MODELISATION_ET_PRICING("Modélisation & Pricing"),
MODELISATION_ET_PRICING("Front-Office"),
PROGRAMMATION_C_SHARP("Programmation C#"),
PROGRAMMATION_JAVA("Programmation Java"),
ARCHITECTURE_ET_DESIGN("Architecture & Design"),
RISQUES("Risques"),
BIG_DATA("Big Data"),
BIG_DATA("Big Data Engineering"),
POST_TRADE("Post-Trade"),
MACHINE_LEARNING("Data Science"),
ANALYTICS_ET_BI("Analytics & BI"),
MOA("MOA Transverse"),
AGILITE_ET_CRAFT("Agilité & Craft"),
DEVOPS("Devops"),
SUPPORT_ET_PRODUCTION_APPLICATIVE("Support & Production Applicative");
SUPPORT_ET_PRODUCTION_APPLICATIVE("Support & Production Applicative"),
UNKNOWN_EXPERTISE("Expertise inconnue");

private String expertiseName;
private final String expertiseName;

Expertise(String expertiseName) {
this.expertiseName = expertiseName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

public enum UserExpertiseStatus {
CONSULTANT_SENIOR_IN_ONBOARDING("Consultant Senior en cours d'onboarding"),
CONSULTANT("Consultant"),
CONSULTANT_SENIOR("Consultant Senior"),
MANAGER("Manager"),
MANAGER_SENIOR("Manager Senior");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,5 @@ public interface PaymentRepository extends JpaRepository<Payment, Long> {

List<Payment> findAllByReceiverOrderByDateDesc(User receiver);

List<Payment> findAllByReceiverOrderByDateAsc(User receiver);

Optional<Payment> findByDateAndReceiver(LocalDate paymentDate, User user);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.invivoo.vivwallet.api.domain.payment;

import com.invivoo.vivwallet.api.domain.action.ActionRepository;
import com.invivoo.vivwallet.api.domain.user.User;
import com.invivoo.vivwallet.api.domain.user.UserRepository;
import com.invivoo.vivwallet.api.interfaces.payments.PaymentDto;
Expand All @@ -19,7 +18,6 @@ public class PaymentService {

private final UserRepository userRepository;
private final PaymentRepository paymentRepository;
private final ActionRepository actionRepository;

public Optional<Payment> findById(Long paymentId) {
return paymentRepository.findById(paymentId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,10 @@


import com.invivoo.vivwallet.api.domain.user.User;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.*;
import org.apache.commons.lang3.builder.HashCodeExclude;

import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import java.util.Objects;
import javax.persistence.*;

@Table(name = "roles", uniqueConstraints = @UniqueConstraint(columnNames = {"user_id", "type"}))
@Entity
Expand All @@ -34,6 +20,7 @@ public class Role {
private Long id;
@ToString.Exclude
@HashCodeExclude
@EqualsAndHashCode.Exclude
@ManyToOne(fetch = FetchType.LAZY)
private User user;
@Enumerated(EnumType.STRING)
Expand All @@ -42,18 +29,4 @@ public class Role {
public Role(RoleType type) {
this.type = type;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Role role = (Role) o;
return Objects.equals(id, role.id) &&
Objects.equals(user, role.user) &&
type == role.type;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,7 @@
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.Set;
Expand All @@ -34,6 +26,8 @@ public class User {
private String x4bId;
@Column(unique = true)
private String fullName;

private String email;
@OneToMany(
mappedBy = "user",
cascade = CascadeType.ALL,
Expand All @@ -58,4 +52,13 @@ public User(Long id, String x4bId, String fullName, Set<UserExpertise> expertise
this.expertises = expertises;
this.roles = roles;
}

public User(Long id, String x4bId, String fullName, String email, Set<UserExpertise> expertises, Set<Role> roles) {
this.id = id;
this.x4bId = x4bId;
this.fullName = fullName;
this.email = email;
this.expertises = expertises;
this.roles = roles;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@
import com.invivoo.vivwallet.api.domain.expertise.Expertise;
import com.invivoo.vivwallet.api.domain.role.RoleType;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;
import java.util.Optional;

public interface UserRepository extends JpaRepository<User, Long> {

@Query("SELECT user FROM User user WHERE upper(user.fullName) = upper(trim(:fullName))")
Optional<User> findByFullNameTrimIgnoreCase(@Param("fullName") String fullName);

Optional<User> findByFullNameIgnoreCase(String owner);

Optional<User> findByX4bIdIgnoreCase(String x4bId);
Expand All @@ -18,4 +23,5 @@ public interface UserRepository extends JpaRepository<User, Long> {

Optional<User> findFirstByRolesType(RoleType type);

Optional<User> findByEmail(String email);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,25 @@
import com.invivoo.vivwallet.api.domain.action.ActionRepository;
import com.invivoo.vivwallet.api.domain.action.ActionStatus;
import com.invivoo.vivwallet.api.domain.expertise.Expertise;
import com.invivoo.vivwallet.api.domain.expertise.UserExpertise;
import com.invivoo.vivwallet.api.domain.payment.Payment;
import com.invivoo.vivwallet.api.domain.payment.PaymentRepository;
import com.invivoo.vivwallet.api.domain.role.Role;
import com.invivoo.vivwallet.api.domain.role.RoleType;
import com.invivoo.vivwallet.api.infrastructure.lynx.LynxConnector;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@PersistenceContext
Expand All @@ -23,11 +31,16 @@ public class UserService {
private final UserRepository userRepository;
private final ActionRepository actionRepository;
private final PaymentRepository paymentRepository;
private final LynxConnector lynxConnector;

public UserService(UserRepository userRepository, ActionRepository actionRepository, PaymentRepository paymentRepository) {
public UserService(UserRepository userRepository,
ActionRepository actionRepository,
PaymentRepository paymentRepository,
LynxConnector lynxConnector) {
this.userRepository = userRepository;
this.actionRepository = actionRepository;
this.paymentRepository = paymentRepository;
this.lynxConnector = lynxConnector;
}

public List<User> findAll() {
Expand All @@ -44,20 +57,25 @@ public Optional<User> findById(Long userId) {

public Optional<User> findByFullName(String fullName) {
return Optional.ofNullable(fullName)
.map(String::trim)
.flatMap(userRepository::findByFullNameIgnoreCase);
.flatMap(userRepository::findByFullNameTrimIgnoreCase);
}

public Optional<User> findByX4bIdOrByFullName(String x4bId) {
Optional<User> userByX4bId = userRepository.findByX4bIdIgnoreCase(x4bId);
if (userByX4bId.isPresent()) {
return userByX4bId;
}
Optional<User> userByFullName = userRepository.findByFullNameIgnoreCase(getFullNameFromX4bId(x4bId));
userByFullName.filter(user -> Objects.isNull(user.getX4bId())).ifPresent(user -> userRepository.save(user.toBuilder().x4bId(x4bId).build()));
String fullNameFromX4bId = getFullNameFromX4bId(x4bId);
Optional<User> userByFullName = userRepository.findByFullNameIgnoreCase(fullNameFromX4bId);
userByFullName.filter(user -> Objects.isNull(user.getX4bId()))
.ifPresent(user -> userRepository.save(user.toBuilder().x4bId(x4bId).build()));
return userByFullName;
}

public Optional<User> findByEmail(String email) {
return userRepository.findByEmail(email);
}

public Optional<User> findByRoleType(RoleType type) {
return userRepository.findFirstByRolesType(type);
}
Expand All @@ -83,7 +101,9 @@ public void deleteAll() {
public int computeBalance(User user) {
LocalDateTime vivInitialBalanceDate = Optional.ofNullable(user.getVivInitialBalanceDate())
.orElse(LocalDateTime.ofEpochSecond(0, 0, ZoneOffset.UTC));
int userBalanceFromActionsInVivAfterInitialBalanceDate = actionRepository.findAllByAchieverAndValueDateAfterAndStatus(user, vivInitialBalanceDate, ActionStatus.PAYABLE)
int userBalanceFromActionsInVivAfterInitialBalanceDate = actionRepository.findAllByAchieverAndValueDateAfterAndStatus(user,
vivInitialBalanceDate,
ActionStatus.PAYABLE)
.stream()
.mapToInt(Action::getVivAmount)
.sum();
Expand All @@ -94,6 +114,64 @@ public int computeBalance(User user) {
return user.getVivInitialBalance() + userBalanceFromActionsInVivAfterInitialBalanceDate - userPaymentsAmountInViv;
}

@Transactional
public List<User> updateFromLynx() {
List<User> users = userRepository.findAll();
Map<String, User> userByFullNameUpperCased = users.stream()
.collect(Collectors.toMap(user -> user.getFullName().toUpperCase(),
Function.identity()));
Map<String, User> usersByEmail = users.stream()
.filter(user -> StringUtils.isNotBlank(user.getEmail()))
.collect(Collectors.toMap(User::getEmail, Function.identity()));
List<User> usersFromLynx = lynxConnector.findUsers();
List<User> updatedAndNewUsers = usersFromLynx.stream()
.map(userFromLynx -> updateUserIfExistsOrElseGetNew(userByFullNameUpperCased,
usersByEmail,
userFromLynx))
.collect(Collectors.toList());
return userRepository.saveAll(updatedAndNewUsers);
}

private User updateUserIfExistsOrElseGetNew(Map<String, User> userByFullNameUpperCased,
Map<String, User> usersByEmail,
User userFromLynx) {
return Optional.ofNullable(userByFullNameUpperCased.get(userFromLynx.getFullName().toUpperCase()))
.or(() -> Optional.ofNullable(usersByEmail.get(userFromLynx.getEmail())))
.map(user -> updateUserFromUserFromLynx(user, userFromLynx))
.orElse(userFromLynx);
}

private User updateUserFromUserFromLynx(User user, User userFromLynx) {
user.setFullName(userFromLynx.getFullName());
user.setEmail(userFromLynx.getEmail());
userFromLynx.getExpertises()
.forEach(userExpertiseFromLynx -> addUserExpertiseIfNoneMatch(user, userExpertiseFromLynx));
userFromLynx.getRoles()
.forEach(userRoleFromLynx -> addRoleIfNoneMatch(user, userRoleFromLynx));
return user;
}

private void addUserExpertiseIfNoneMatch(User user, UserExpertise userExpertiseFromLynx) {
if (user.getExpertises()
.stream()
.anyMatch(userExpertise -> userExpertise.getExpertise().equals(userExpertiseFromLynx.getExpertise())
&& userExpertise.getStatus().equals(userExpertiseFromLynx.getStatus()))) {
return;
}
userExpertiseFromLynx.setUser(user);
user.getExpertises().add(userExpertiseFromLynx);
}

private void addRoleIfNoneMatch(User user, Role roleFromLynx) {
if (user.getRoles()
.stream()
.anyMatch(role -> role.getType().equals(roleFromLynx.getType()))) {
return;
}
roleFromLynx.setUser(user);
user.getRoles().add(roleFromLynx);
}

private void updateRelatedEntitiesWithUser(User user) {
Optional.ofNullable(user.getRoles())
.ifPresent(roles -> roles.forEach(r -> r.setUser(user)));
Expand Down
Loading

0 comments on commit 527a43a

Please sign in to comment.