Skip to content

Commit

Permalink
feat: improve contact endpoints for management front (#82)
Browse files Browse the repository at this point in the history
* feat: improve contact endpoints for management front

* feat: improve contact endpoints

* fix: contact search request

* fix: parameters method in search contact

* feat: update search survey unit controller

* feat: update Dto to add function and remove list sources

* fix: search contact upper case

* fix: search contact upper case

* feat: update survey unit endpoints for pilotage management front

* feat: update survey unit endpoints for pilotage management front

* fix: had survey unit questioning informations

* fix: sonar issues

* fix: remove cucumber test

* test: add search contact cucumber test

* tests: improve cucumber test

* feat: improve search contact

* fix: imporve validation message in search contact

* fix: search contact with special characters

* fix: cucumber tests for search contact

* feat: add search survey unit

* tests: add cucumber tests to search survey units

* test: fix test search survey unit

* tests: refactor

* refactor: set status in annotation

* refactor: spelling postgres for Simon

* chore: update spring boot version

* fix: moog bug when zip code is null
  • Loading branch information
BettyB979 authored Sep 20, 2024
1 parent 247ea20 commit f7393e1
Show file tree
Hide file tree
Showing 62 changed files with 1,093 additions and 406 deletions.
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
</parent>
<groupId>fr.insee.survey</groupId>
<artifactId>platine-management</artifactId>
<version>2.5.1</version>
<version>2.6.0</version>
<name>platine-management</name>
<description>REST API for communication between DB and Platine-Management UI and Platine-My-Surveys UI</description>
<properties>
Expand All @@ -20,7 +20,7 @@
<modelmapper-version>3.2.0</modelmapper-version>
<jakarta-version>3.1.0</jakarta-version>
<easy-version>5.0.0</easy-version>
<postgre-version>42.7.3</postgre-version>
<postgres-version>42.7.3</postgres-version>
<javafaker-version>1.0.2</javafaker-version>
<sonar.organization>inseefr</sonar.organization>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
Expand Down Expand Up @@ -87,7 +87,7 @@
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgre-version}</version>
<version>${postgres-version}</version>
</dependency>
<!-- SECURITY -->
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,8 @@
public class AuthConstants {

public static final String OIDC = "OIDC";

private AuthConstants() {
throw new IllegalStateException("Utility class");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ private Constants() {
public static final String API_SURVEY_UNITS ="/api/survey-units";
public static final String API_SURVEY_UNITS_ID = "/api/survey-units/{id}";
public static final String API_SURVEY_UNITS_ID_QUESTIONINGS = "/api/survey-units/{id}/questionings";
public static final String API_SURVEY_UNITS_ID_COMMENT = "/api/survey-units/{id}/comment";

public static final String API_QUESTIONINGS_ID_QUESTIONING_ACCREDITATIONS = "/api/questionings/{id}/questioning-accreditations";
public static final String API_QUESTIONING_QUESTIONING_EVENTS = "/api/questionings/questioning-events";
public static final String API_QUESTIONING_ID_QUESTIONING_EVENTS = "/api/questionings/{id}/questioning-events";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,13 @@ public class AddressController {

private final ContactEventService contactEventService;

/**
* @deprecated
*/
@Operation(summary = "Search for a contact address by the contact id")
@GetMapping(value = Constants.API_CONTACTS_ID_ADDRESS, produces = "application/json")
@PreAuthorize(AuthorityPrivileges.HAS_MANAGEMENT_PRIVILEGES + " || " + AuthorityPrivileges.HAS_REPONDENT_LIMITATED_PRIVILEGES)
@Deprecated(since="2.6.0", forRemoval=true)
public ResponseEntity<AddressDto> getContactAddress(@PathVariable("id") String id) {
Contact contact = contactService.findByIdentifier(id);
if (contact.getAddress() != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,25 @@
import fr.insee.survey.datacollectionmanagement.config.auth.user.AuthorityPrivileges;
import fr.insee.survey.datacollectionmanagement.constants.Constants;
import fr.insee.survey.datacollectionmanagement.contact.domain.Contact;
import fr.insee.survey.datacollectionmanagement.contact.domain.ContactEvent.ContactEventType;
import fr.insee.survey.datacollectionmanagement.contact.dto.ContactDetailsDto;
import fr.insee.survey.datacollectionmanagement.contact.dto.ContactDto;
import fr.insee.survey.datacollectionmanagement.contact.dto.ContactFirstLoginDto;
import fr.insee.survey.datacollectionmanagement.contact.dto.SearchContactDto;
import fr.insee.survey.datacollectionmanagement.contact.service.AddressService;
import fr.insee.survey.datacollectionmanagement.contact.service.ContactService;
import fr.insee.survey.datacollectionmanagement.contact.util.ContactParamEnum;
import fr.insee.survey.datacollectionmanagement.contact.util.PayloadUtil;
import fr.insee.survey.datacollectionmanagement.contact.validation.ValidContactParam;
import fr.insee.survey.datacollectionmanagement.exception.ImpossibleToDeleteException;
import fr.insee.survey.datacollectionmanagement.exception.NotFoundException;
import fr.insee.survey.datacollectionmanagement.exception.NotMatchException;
import fr.insee.survey.datacollectionmanagement.questioning.service.QuestioningAccreditationService;
import fr.insee.survey.datacollectionmanagement.view.service.ViewService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
Expand All @@ -34,6 +41,7 @@
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import java.io.Serial;
import java.util.Collections;
import java.util.List;

@RestController
Expand All @@ -54,24 +62,29 @@ public class ContactController {

private final ModelMapper modelMapper;

/**
* @deprecated
*/
@Operation(summary = "Search for contacts, paginated")
@GetMapping(value = Constants.API_CONTACTS_ALL, produces = "application/json")
public ResponseEntity<ContactPage> getContacts(
@Deprecated(since = "2.6.0", forRemoval = true)
public ContactPage getContacts(
@RequestParam(defaultValue = "0") Integer page,
@RequestParam(defaultValue = "20") Integer size,
@RequestParam(defaultValue = "identifier") String sort) {
Pageable pageable = PageRequest.of(page, size, Sort.by(sort));
Page<Contact> pageC = contactService.findAll(pageable);
List<ContactDto> listC = pageC.stream().map(this::convertToDto).toList();
return ResponseEntity.ok().body(new ContactPage(listC, pageable, pageC.getTotalElements()));
return new ContactPage(listC, pageable, pageC.getTotalElements());
}

@Operation(summary = "Search for a contact by its id")
@GetMapping(value = Constants.API_CONTACTS_ID)
@PreAuthorize(AuthorityPrivileges.HAS_MANAGEMENT_PRIVILEGES + " || " + AuthorityPrivileges.HAS_REPONDENT_LIMITATED_PRIVILEGES)
public ResponseEntity<ContactFirstLoginDto> getContact(@PathVariable("id") String id) {
public ContactDetailsDto getContact(@PathVariable("id") String id) {
Contact contact = contactService.findByIdentifier(StringUtils.upperCase(id));
return ResponseEntity.ok().body(convertToFirstLoginDto(contact));
List<String> listCampaigns = questioningAccreditationService.findCampaignsForContactId(id);
return convertToContactDetailsDto(contact, listCampaigns);


}
Expand Down Expand Up @@ -112,9 +125,13 @@ public ResponseEntity<ContactDto> putContact(@PathVariable("id") String id,
}


/**
* @deprecated
*/
@Operation(summary = "Delete a contact, its address, its contactEvents")
@DeleteMapping(value = Constants.API_CONTACTS_ID)
@ResponseStatus(HttpStatus.NO_CONTENT)
@Deprecated(since = "2.6.0", forRemoval = true)
public void deleteContact(@PathVariable("id") String id) {

if (!questioningAccreditationService.findByContactIdentifier(id).isEmpty()) {
Expand All @@ -128,17 +145,47 @@ public void deleteContact(@PathVariable("id") String id) {

}

@GetMapping(path = Constants.API_CONTACTS_SEARCH, produces = "application/json")
@Operation(summary = "Multi-criteria search contacts")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = SearchContactDto.class)))),
@ApiResponse(responseCode = "400", description = "Bad Request")
})
public Page<SearchContactDto> searchContacts(
@RequestParam(required = true) String searchParam,
@RequestParam(required = false) @Valid @ValidContactParam String searchType,
@RequestParam(defaultValue = "0") Integer page,
@RequestParam(defaultValue = "10") Integer pageSize,
@RequestParam(defaultValue = "identifier") String sort) {

log.info(
"Search contact by {} with param = {} page = {} pageSize = {}", searchType, searchParam, page, pageSize);

Pageable pageable = PageRequest.of(page, pageSize, Sort.by(sort));

switch (ContactParamEnum.fromValue(searchType)) {
case ContactParamEnum.IDENTIFIER:
return contactService.searchContactByIdentifier(searchParam, pageable);
case ContactParamEnum.NAME:
return contactService.searchContactByName(searchParam, pageable);
case ContactParamEnum.EMAIL:
return contactService.searchContactByEmail(searchParam, pageable);
}
return new PageImpl<>(Collections.emptyList());

}

private ContactDto convertToDto(Contact contact) {
ContactDto contactDto = modelMapper.map(contact, ContactDto.class);
contactDto.setCivility(contact.getGender().name());
return contactDto;
}

private ContactFirstLoginDto convertToFirstLoginDto(Contact contact) {
ContactFirstLoginDto contactFirstLoginDto = modelMapper.map(contact, ContactFirstLoginDto.class);
contactFirstLoginDto.setCivility(contact.getGender());
contactFirstLoginDto.setFirstConnect(contact.getContactEvents().stream().noneMatch(e -> e.getType().equals(ContactEventType.firstConnect)));
return contactFirstLoginDto;
private ContactDetailsDto convertToContactDetailsDto(Contact contact, List<String> listCampaigns) {
ContactDetailsDto contactDetailsDto = modelMapper.map(contact, ContactDetailsDto.class);
contactDetailsDto.setCivility(contact.getGender());
contactDetailsDto.setListCampaigns(listCampaigns);
return contactDetailsDto;
}

private Contact convertToEntity(ContactDto contactDto) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,12 @@ public class ContactEventController {

private final ModelMapper modelMapper;

/**
* @deprecated
*/
@Operation(summary = "Search for contactEvents by the contact id")
@GetMapping(value = Constants.API_CONTACTS_ID_CONTACTEVENTS, produces = "application/json")
@Deprecated(since = "2.6.0", forRemoval = true)
public ResponseEntity<List<ContactEventDto>> getContactContactEvents(@PathVariable("id") String identifier) {
Contact contact = contactService.findByIdentifier(identifier);
return ResponseEntity.status(HttpStatus.OK)
Expand All @@ -50,8 +54,13 @@ public ResponseEntity<List<ContactEventDto>> getContactContactEvents(@PathVariab

}


/**
* @deprecated
*/
@Operation(summary = "Create a contactEvent")
@PostMapping(value = Constants.API_CONTACTEVENTS, produces = "application/json", consumes = "application/json")
@Deprecated(since = "2.6.0", forRemoval = true)
public ResponseEntity<ContactEventDto> postContactEvent(@RequestBody @Valid ContactEventDto contactEventDto) {

Contact contact = contactService.findByIdentifier(contactEventDto.getIdentifier());
Expand All @@ -70,9 +79,14 @@ public ResponseEntity<ContactEventDto> postContactEvent(@RequestBody @Valid Cont
}



/**
* @deprecated
*/
@Operation(summary = "Delete a contact event")
@DeleteMapping(value = Constants.API_CONTACTEVENTS_ID, produces = "application/json")
@ResponseStatus(HttpStatus.NO_CONTENT)
@Deprecated(since = "2.6.0", forRemoval = true)
public void deleteContactEvent(@PathVariable("id") Long id) {
ContactEvent contactEvent = contactEventService.findById(id);
Contact contact = contactEvent.getContact();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
import lombok.Getter;
import lombok.Setter;

import java.util.List;

@Getter
@Setter
public class ContactFirstLoginDto{
public class ContactDetailsDto {

private String identifier;
private String externalId;
Expand All @@ -20,7 +22,7 @@ public class ContactFirstLoginDto{
private String phone;
private String otherPhone;
private String usualCompanyName;
private boolean firstConnect;
private AddressDto address;
private List<String> listCampaigns;

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package fr.insee.survey.datacollectionmanagement.query.dto;

public interface SearchContactDto {
String getIdentifier();
String getEmail();
String getFirstName();
String getLastName();
}
package fr.insee.survey.datacollectionmanagement.contact.dto;

public interface SearchContactDto {
String getIdentifier();
String getEmail();
String getFirstName();
String getLastName();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package fr.insee.survey.datacollectionmanagement.contact.dto;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class SearchContactDtoImpl implements SearchContactDto{

private String identifier;
private String email;
private String firstName;
private String lastName;
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package fr.insee.survey.datacollectionmanagement.contact.repository;

import fr.insee.survey.datacollectionmanagement.contact.domain.Contact;
import fr.insee.survey.datacollectionmanagement.query.dto.SearchContactDto;
import fr.insee.survey.datacollectionmanagement.contact.dto.SearchContactDto;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
Expand All @@ -18,36 +18,52 @@ public interface ContactRepository extends PagingAndSortingRepository<Contact, S

@Query(nativeQuery = true, value = "SELECT identifier FROM contact TABLESAMPLE system_rows(1)")
String findRandomIdentifierContact();

@Query(
value = """
SELECT
c.identifier as identifier,
c.email as email,
c.first_name as firstName,
c.last_name as lastName
FROM
contact c
WHERE
:param IS NULL
OR (
UPPER(c.identifier) LIKE CONCAT(:param, '%')
OR UPPER(CONCAT(c.last_name)) LIKE CONCAT(:param, '%')
OR UPPER(CONCAT(c.first_name, ' ', c.last_name)) LIKE CONCAT(:param, '%')
OR UPPER(c.email) LIKE CONCAT(:param, '%')
)
""",
value = """
SELECT
c.identifier as identifier,
c.email as email,
c.first_name as firstName,
c.last_name as lastName
FROM
contact c
WHERE
UPPER(c.identifier) LIKE CONCAT(UPPER(:param), '%')
""",
nativeQuery = true
)
Page<SearchContactDto> findByParameter(String param, Pageable pageable);

Page<SearchContactDto> findByIdentifierIgnoreCaseStartingWithOrFirstNameIgnoreCaseStartingWithOrLastNameIgnoreCaseStartingWithOrEmailIgnoreCaseStartingWith(String identifier, String firstName, String lastName, String email, Pageable pageable);

@Query(nativeQuery = true, value = "SELECT * FROM contact c WHERE UPPER(CONCAT(c.first_name, ' ', c.last_name)) LIKE CONCAT(:param, '%')")
Page<SearchContactDto> findByFirstNameLastName( String param, Pageable pageable);

@Query(nativeQuery = true, value = "SELECT * FROM contact")
Page<SearchContactDto> findAllNoParameters(Pageable pageable);
Page<SearchContactDto> findByIdentifier( String param, Pageable pageable);

@Query(
value = """
SELECT
c.identifier as identifier,
c.email as email,
c.first_name as firstName,
c.last_name as lastName
FROM
contact c
WHERE
UPPER(c.email) LIKE CONCAT(UPPER(:param), '%')
""",
nativeQuery = true
)
Page<SearchContactDto> findByEmail( String param, Pageable pageable);
@Query(
value = """
SELECT
c.identifier as identifier,
c.email as email,
c.first_name as firstName,
c.last_name as lastName
FROM
contact c
WHERE
UPPER(c.last_name) LIKE CONCAT(UPPER(:param), '%')
OR UPPER(CONCAT(c.first_name, ' ', c.last_name)) LIKE CONCAT(UPPER(:param), '%')
""",
nativeQuery = true
)
Page<SearchContactDto> findByFirstNameLastName(String param, Pageable pageable);

}
Loading

0 comments on commit f7393e1

Please sign in to comment.