Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion extract/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,12 @@
<artifactId>javase</artifactId>
<version>3.5.3</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<scope>test</scope>
<type>jar</type>
</dependency>
</dependencies>

<profiles>
Expand Down Expand Up @@ -262,7 +268,7 @@
<skipTests>false</skipTests>
<summaryFile>target/failsafe-reports/failsafe-summary-integration.xml</summaryFile>
<includes>
<include>ch.asit_asso.extract.integration.**.*IntegrationTest</include>
<include>ch.asit_asso.extract.integration.**.*RequestsOwnershipIntegrationTest</include>
</includes>
<systemPropertyVariables>
<extract.log.path>${project.build.directory}/logs</extract.log.path>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright (C) 2025 arusakov
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ch.asit_asso.extract.configuration;

import java.text.MessageFormat;
import java.util.Locale;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.core.env.Environment;
import org.springframework.util.StringValueResolver;

/**
* A MessageSource that resolves ${…} placeholders against the Spring {@link Environment}
* after the message has been loaded from the bundle.
*/
public class EnvResolvingMessageSource extends ReloadableResourceBundleMessageSource
implements EnvironmentAware {

private StringValueResolver placeholderResolver;

@Override
public void setEnvironment(Environment environment) {
// Spring already knows how to resolve ${…} against the environment,
// we just delegate to its built‑in resolver.
this.placeholderResolver = environment::resolveRequiredPlaceholders;
}

@Override
protected String resolveCodeWithoutArguments(String code, Locale locale) {
var raw = super.resolveCodeWithoutArguments(code, locale);

return raw == null || placeholderResolver == null ? raw :
placeholderResolver.resolveStringValue(raw);
}

@Override
protected MessageFormat resolveCode(String code, Locale locale) {
var raw = super.resolveCode(code, locale);
if (raw != null && placeholderResolver != null) {
raw.applyPattern(placeholderResolver.resolveStringValue(raw.toPattern()));
}
return raw;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public class I18nConfiguration {
@Bean
public MessageSource messageSource() {
this.logger.debug("Configuring the message source for languages: {}.", this.language);
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
EnvResolvingMessageSource messageSource = new EnvResolvingMessageSource();

// la collection des base names
List<String> basenames = new ArrayList<>();
Expand Down
111 changes: 110 additions & 1 deletion extract/src/main/java/ch/asit_asso/extract/domain/Request.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@

import java.io.Serializable;
import java.util.Calendar;
import java.util.Collection;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
Expand All @@ -28,13 +31,16 @@
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlTransient;
import org.apache.commons.lang3.StringUtils;


Expand Down Expand Up @@ -252,7 +258,40 @@ public class Request implements Serializable {
private Connector connector;



/**
* The operators that supervise this process.
*/
@JoinTable(name = "requests_users",
joinColumns = {
@JoinColumn(name = "id_request", referencedColumnName = "id_request",
foreignKey = @ForeignKey(name = "FK_REQUESTS_USERS_REQUESTS")
)
},
inverseJoinColumns = {
@JoinColumn(name = "id_user", referencedColumnName = "id_user",
foreignKey = @ForeignKey(name = "FK_REQUESTS_USERS_USER")
)
}
)
@ManyToMany
private Collection<User> usersCollection;


@JoinTable(name = "requests_usergroups",
joinColumns = {
@JoinColumn(name = "id_request", referencedColumnName = "id_request",
foreignKey = @ForeignKey(name = "FK_REQUESTS_USERGROUPS_REQUESTS")
)
},
inverseJoinColumns = {
@JoinColumn(name = "id_usergroup", referencedColumnName = "id_usergroup",
foreignKey = @ForeignKey(name = "FK_REQUESTS_USERGROUPS_USERGROUP")
)
}
)
@ManyToMany
private Collection<UserGroup> userGroupsCollection;

/**
* The possible states of a data item order processing.
*/
Expand Down Expand Up @@ -1006,4 +1045,74 @@ public final void reject(final String rejectionRemark) {
this.setRejected(true);
}


/**
* Obtains the users that supervise this particular task. This only contains the users defined
* directly, not those defined through a user group. To get all the operators independently of
* how they've been defined, please use the method
* {@link #getDistinctOperators()}
*
* @return a collection that contains the operators
*/
@XmlTransient
public Collection<User> getUsersCollection() {
return usersCollection;
}



/**
* Defines the users that supervise this particular task.
*
* @param users a collection that contains the operators for this task
*/
public void setUsersCollection(final Collection<User> users) {
this.usersCollection = users;
}


/**
* Obtains the user groups that supervise this particular task.
*
* @return a collection that contains the groups of operators
*/
@XmlTransient
public Collection<UserGroup> getUserGroupsCollection() {
return userGroupsCollection;
}



/**
* Defines the user groups that supervise this particular task.
*
* @param userGroups a collection that contains the groups of operators for this task
*/
public void setUserGroupsCollection(Collection<UserGroup> userGroups) {
this.userGroupsCollection = userGroups;
}

/**
* Obtains a list of all the users allowed to manage this process, including those defined through a user group,
* without duplicates.
*
* @return a collection that contains all the operators for this process
*/
public final Collection<User> getDistinctOperators() {
List<User> operators = new ArrayList<>(this.getUsersCollection());

for (UserGroup operatorsGroup : this.getUserGroupsCollection()) {

for (User groupOperator : operatorsGroup.getUsersCollection()) {

if (operators.contains((groupOperator))) {
continue;
}

operators.add(groupOperator);
}
}

return operators;
}
}
18 changes: 12 additions & 6 deletions extract/src/main/java/ch/asit_asso/extract/domain/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,19 @@
@NamedQuery(name = "User.findAllActiveApplicationUsers",
query = "SELECT u FROM User u WHERE u.login != " + "'" + User.SYSTEM_USER_LOGIN + "' and u.active = true"),
@NamedQuery(name = "User.getUserAssociatedRequestsByStatusOrderByEndDate",
query = "SELECT r FROM Request r WHERE (r.process IN (SELECT p FROM User u JOIN u.processesCollection p WHERE u.id = :userId)"
+ " OR r.process IN (SELECT p FROM User u JOIN u.userGroupsCollection g JOIN g.processesCollection p WHERE u.id = :userId))"
+ " AND r.status = :status ORDER BY r.endDate DESC"),
query = "SELECT r FROM Request r WHERE ("
+ " r.process IN (SELECT p FROM User u JOIN u.processesCollection p WHERE u.id = :userId)"
+ " OR r.process IN (SELECT p FROM User u JOIN u.userGroupsCollection g JOIN g.processesCollection p WHERE u.id = :userId)"
+ " OR :userId IN (SELECT uc.id FROM r.usersCollection uc)"
+ " OR :userId IN (SELECT uc.id FROM r.userGroupsCollection ug LEFT JOIN ug.usersCollection uc)"
+ ") AND r.status = :status ORDER BY r.endDate DESC"),
@NamedQuery(name = "User.getUserAssociatedRequestsByStatusNot",
query = "SELECT r FROM Request r WHERE (r.process IN (SELECT p FROM User u JOIN u.processesCollection p WHERE u.id = :userId)"
+ " OR r.process IN (SELECT p FROM User u JOIN u.userGroupsCollection g JOIN g.processesCollection p WHERE u.id = :userId))"
+ " AND r.status != :status")
query = "SELECT r FROM Request r WHERE ("
+ " r.process IN (SELECT p FROM User u JOIN u.processesCollection p WHERE u.id = :userId)"
+ " OR r.process IN (SELECT p FROM User u JOIN u.userGroupsCollection g JOIN g.processesCollection p WHERE u.id = :userId)"
+ " OR :userId IN (SELECT uc.id FROM r.usersCollection uc)"
+ " OR :userId IN (SELECT uc.id FROM r.userGroupsCollection ug LEFT JOIN ug.usersCollection uc)"
+ ") AND r.status != :status")


})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import ch.asit_asso.extract.domain.Process;
import ch.asit_asso.extract.domain.Request;
import ch.asit_asso.extract.domain.Request_;
import ch.asit_asso.extract.domain.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.jpa.domain.Specification;
Expand Down Expand Up @@ -237,7 +238,28 @@ public Predicate toPredicate(final Root<Request> root, final CriteriaQuery<?> qu
};
}

/**
* Obtains the criteria to filter the request based on the process it is associated with.
*
* @param processesList a list that contains the process that the request can be associated with
* @return the set of criteria to apply the process filter
*/
public static Specification<Request> isBoundToUser(final User user) {

return new Specification<Request>() {

@Override
public Predicate toPredicate(final Root<Request> root, final CriteriaQuery<?> query,
final CriteriaBuilder builder) {
var result = builder.isMember(user, root.get(Request_.usersCollection));
for (var ug: user.getUserGroupsCollection()) {
result = builder.or(result, builder.isMember(ug, root.get(Request_.userGroupsCollection)));
}
return result;
}

};
}

/**
* Obtains the criteria to return only the request whose process has completed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -501,8 +501,10 @@ private Page<Request> getFinishedRequests(final int pageStart, final String sort
String.join(", ",
userProcesses.stream().map((process) ->
process.getId().toString()).toArray(String[]::new)));

final Specification<Request> userCriteria
= RequestSpecification.isProcessInList(userProcesses);
= RequestSpecification.isProcessInList(userProcesses).or(
RequestSpecification.isBoundToUser(currentUser));

return this.requestsRepository.findAll(Specification.where(userCriteria).and(searchCriteria), paging);
}
Expand Down
Loading