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

New feature to add chat link to user #1566

Merged
merged 5 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: |
git fetch --unshallow
mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent install sonar:sonar -Dsonar.projectKey=ita-social-projects-green-ubs -Dsonar.organization=ita-social-projects -Dsonar.host.url=https://sonarcloud.io -Dsonar.binaries=target/classes -Dsonar.dynamicAnalysis=reuseReports -Dsonar.exclusions=**/EncryptionUtil.java -Dsonar.coverage.exclusions=**/configuration/*,**/entity/*,**/exceptions/*,**/exceptions/**,**/enums/NotificationType.java,**/BigOrderTableRepository.java
mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent install sonar:sonar -Dsonar.projectKey=ita-social-projects-green-ubs -Dsonar.organization=ita-social-projects -Dsonar.host.url=https://sonarcloud.io -Dsonar.binaries=target/classes -Dsonar.dynamicAnalysis=reuseReports -Dsonar.exclusions=**/EncryptionUtil.java -Dsonar.coverage.exclusions=**/configuration/*,**/entity/*,**/exceptions/*,**/exceptions/**,**/enums/NotificationType.java,**/BigOrderTableRepository.java,**/ChatLinkDto.java

- name: Test Reporter
uses: dorny/[email protected]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,8 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
.hasAnyRole(ADMIN, UBS_EMPLOYEE)
.requestMatchers(HttpMethod.PATCH,
SUPER_ADMIN_LINK + "/deactivateCourier/{id}",
SUPER_ADMIN_LINK + "/switchTariffStatus/{tariffId}")
SUPER_ADMIN_LINK + "/switchTariffStatus/{tariffId}",
UBS_MANAG_LINK + "/addChatLink")
.hasAnyRole(ADMIN, UBS_EMPLOYEE)
.requestMatchers(HttpMethod.PATCH,
UBS_MANAG_LINK + "/update-order-page-admin-info/{id}",
Expand Down
15 changes: 15 additions & 0 deletions core/src/main/java/greencity/controller/AdminUbsController.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import greencity.dto.pageble.PageableDto;
import greencity.dto.table.ColumnWidthDto;
import greencity.dto.table.TableParamsDto;
import greencity.dto.user.ChatLinkDto;
import greencity.dto.violation.UserViolationsWithUserName;
import greencity.enums.SortingOrder;
import greencity.filters.CustomerPage;
Expand Down Expand Up @@ -270,4 +271,18 @@ public ResponseEntity<HttpStatus> saveIsFreeze(@CurrentUserUuid String uuid,
bigOrderTableServiceView.changeIsFreezeStatus(uuid, value);
return ResponseEntity.status(HttpStatus.OK).body(HttpStatus.OK);
}

@Operation(summary = "Add chat link to user")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = HttpStatuses.OK),
@ApiResponse(responseCode = "401", description = HttpStatuses.UNAUTHORIZED, content = @Content),
@ApiResponse(responseCode = "400", description = HttpStatuses.BAD_REQUEST, content = @Content),
@ApiResponse(responseCode = "403", description = HttpStatuses.FORBIDDEN, content = @Content)
})
@PreAuthorize("@preAuthorizer.hasAuthority('SEE_CLIENTS_PAGE', authentication)")
@PatchMapping("/addChatLink")
public ResponseEntity<HttpStatus> addChatLink(@RequestBody @Valid ChatLinkDto chatLink) {
ordersAdminsPageService.addChatLinkToUser(chatLink);
return ResponseEntity.status(HttpStatus.OK).build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import greencity.dto.order.ChangeOrderResponseDTO;
import greencity.dto.order.RequestToChangeOrdersDataDto;
import greencity.dto.table.ColumnWidthDto;
import greencity.dto.user.ChatLinkDto;
import greencity.service.ubs.OrdersAdminsPageService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand All @@ -25,6 +26,7 @@
import static greencity.ModelUtils.getUuid;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
Expand Down Expand Up @@ -154,4 +156,15 @@ void getAllLocations() throws Exception {
.principal(principal))
.andExpect(status().isOk());
}

@Test
void addChatLinkTest() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
mockMvc.perform(patch(management + "/addChatLink")
.principal(principal)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper
.writeValueAsString(new ChatLinkDto(1L, "https://my.binotel.ua/f/chat/#/visitor/21269249.12893974"))))
.andExpect(status().isOk());
}
}
3 changes: 3 additions & 0 deletions dao/src/main/java/greencity/entity/user/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,7 @@ public class User {

@Column(name = "date_of_registration")
private LocalDate dateOfRegistration;

@Column(name = "chat_link")
private String chatLink;
}
Original file line number Diff line number Diff line change
Expand Up @@ -261,4 +261,5 @@
<include file="db/changelog/logs/2024-12-16-hotfix-big_order_table-Kizerov.xml"/>
<include file="db/changelog/logs/2024-11-28-change-add-column-isTableFreeze-to-column_width_for_employee-Warded120.xml"/>
<include file="db/changelog/logs/2024-12-18-update-column_width_for_employee-Kizerov.xml"/>
<include file="db/changelog/logs/2024-12-18-add-new-column-to-user-table-Kizerov.xml"/>
</databaseChangeLog>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">

<changeSet id="add-new-column-to-user" author="Kizerov Dmytro">
<addColumn tableName="users">
<column name="chat_link" type="VARCHAR(500)">
<constraints nullable="true"/>
</column>
</addColumn>
</changeSet>
</databaseChangeLog>
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ public class UserWithSomeOrderDetailDto {
private int violation;
@JsonProperty("currentPoints")
private String userBonuses;
private String chatLink;
}
12 changes: 12 additions & 0 deletions service-api/src/main/java/greencity/dto/user/ChatLinkDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package greencity.dto.user;

import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import org.hibernate.validator.constraints.Length;

public record ChatLinkDto(
Long userId,
@JsonProperty("link") @Length(max = 255) @NotBlank @Pattern(regexp = "^https://my\\.binotel\\.ua.*",
message = "Link must start with 'https://my.binotel.ua'") String link) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import greencity.dto.order.RequestToChangeOrdersDataDto;
import greencity.dto.table.ColumnWidthDto;
import greencity.dto.table.TableParamsDto;
import greencity.dto.user.ChatLinkDto;
import greencity.entity.user.employee.Employee;
import java.util.List;

Expand Down Expand Up @@ -136,4 +137,12 @@ ChangeOrderResponseDTO chooseOrdersDataSwitcher(String email,
* regions, cities, and districts in the system
*/
List<RegionInfoDto> getAllLocationsInfo();

/**
* Adds a chat link to a user.
*
* @param chatLinkDto the chat link to add
* @author Kizerov Dmytro
*/
void addChatLinkToUser(ChatLinkDto chatLinkDto);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import greencity.dto.table.ColumnDTO;
import greencity.dto.table.ColumnWidthDto;
import greencity.dto.table.TableParamsDto;
import greencity.dto.user.ChatLinkDto;
import greencity.entity.table.TableColumnWidthForEmployee;
import greencity.entity.user.Region;
import greencity.entity.user.employee.Employee;
Expand Down Expand Up @@ -89,6 +90,7 @@
import static greencity.constant.ErrorMessage.ORDER_STATUS_NOT_FOUND;
import static greencity.constant.ErrorMessage.ORDER_WITH_CURRENT_ID_DOES_NOT_EXIST;
import static greencity.constant.ErrorMessage.POSITION_NOT_FOUND_BY_ID;
import static greencity.constant.ErrorMessage.USER_WITH_CURRENT_ID_DOES_NOT_EXIST;
import static greencity.constant.ErrorMessage.USER_WITH_CURRENT_UUID_DOES_NOT_EXIST;
import static greencity.constant.OrderHistory.UBS_ADMIN;
import static java.util.Objects.isNull;
Expand Down Expand Up @@ -447,6 +449,17 @@ public List<RegionInfoDto> getAllLocationsInfo() {
.toList();
}

/**
* {@inheritDoc}
*/
@Override
public void addChatLinkToUser(ChatLinkDto chatLinkDto) {
User user = userRepository.findById(chatLinkDto.userId())
.orElseThrow(() -> new NotFoundException(USER_WITH_CURRENT_ID_DOES_NOT_EXIST));
user.setChatLink(chatLinkDto.link());
userRepository.save(user);
}

private RegionInfoDto toRegionInfoDto(Region region) {
return RegionInfoDto.builder()
.id(region.getId())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import greencity.repository.EmployeeRepository;
import greencity.repository.UserRepository;
import greencity.repository.UserTableRepo;
import java.util.Objects;
import lombok.AllArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
Expand Down Expand Up @@ -89,6 +90,9 @@ private UserWithSomeOrderDetailDto mapToDto(User u) {
.setLastOrderDate(optional
.get().getOrderDate().toLocalDate().format(DateTimeFormatter.ofPattern(DATE_FORMAT)));
}
if (Objects.nonNull(u.getChatLink())) {
allFieldsFromTableDto.setChatLink(u.getChatLink());
}
return allFieldsFromTableDto;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import greencity.dto.order.ChangeOrderResponseDTO;
import greencity.dto.order.RequestToChangeOrdersDataDto;
import greencity.dto.table.ColumnWidthDto;
import greencity.dto.user.ChatLinkDto;
import greencity.entity.order.Event;
import greencity.entity.table.TableColumnWidthForEmployee;
import greencity.entity.user.ubs.OrderAddress;
Expand Down Expand Up @@ -1355,4 +1356,15 @@ void addNewCommentWithNotExistingOrderTest() {
verify(employeeRepository).findByEmail(anyString());
verify(orderRepository).findById(anyLong());
}

@Test
void addChatLinkToUserTest() {
when(userRepository.findById(anyLong())).thenReturn(Optional.ofNullable(ModelUtils.getUser()));

ordersAdminsPageService
.addChatLinkToUser(new ChatLinkDto(1L, "https://my.binotel.ua/f/chat/#/visitor/21269249.12893974"));

verify(userRepository).findById(anyLong());
verify(userRepository).save(any(User.class));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package greencity.service.ubs;

import greencity.dto.order.UserWithSomeOrderDetailDto;
import greencity.dto.pageble.PageableDto;
import greencity.entity.order.Order;
import greencity.entity.user.User;
import greencity.entity.user.employee.Employee;
import greencity.enums.SortingOrder;
import greencity.filters.CustomerPage;
import greencity.filters.UserFilterCriteria;
import greencity.repository.EmployeeRepository;
import greencity.repository.UserRepository;
import greencity.repository.UserTableRepo;
import jakarta.persistence.EntityNotFoundException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

@ExtendWith(MockitoExtension.class)
class ValuesForUserTableServiceImplTest {
@Mock
private UserRepository userRepository;

@Mock
private UserTableRepo userTableRepo;

@Mock
private EmployeeRepository employeeRepository;

@InjectMocks
private ValuesForUserTableServiceImpl service;

private static final String TEST_EMAIL = "[email protected]";

@Test
void getAllFieldsShouldReturnPageableDtoWhenDataIsValid() {
Long employeeId = 1L;
List<Long> tariffsInfoIds = List.of(2L, 3L);
List<Long> userIds = List.of(4L, 5L, 4L, 5L);
User user1 = createTestUser(4L, "John", "Doe", "[email protected]", "+380123456789");
User user2 = createTestUser(5L, "Jane", "Smith", "[email protected]", "+380987654321");
Page<User> mockPage = new PageImpl<>(List.of(user1, user2), PageRequest.of(0, 2), 2);

CustomerPage page = new CustomerPage(0, 2);
String columnName = "name";
SortingOrder sortingOrder = SortingOrder.ASC;
UserFilterCriteria filterCriteria = new UserFilterCriteria();

Mockito.when(employeeRepository.findByEmail(TEST_EMAIL))
.thenReturn(Optional.of(createTestEmployee(employeeId)));
Mockito.when(employeeRepository.findTariffsInfoForEmployee(employeeId))
.thenReturn(tariffsInfoIds);
Mockito.when(userRepository.getAllUsersByTariffsInfoId(Mockito.anyLong()))
.thenReturn(List.of(4L, 5L));
Mockito.when(userTableRepo.findAll(
Mockito.eq(filterCriteria),
Mockito.eq(columnName),
Mockito.eq(sortingOrder),
Mockito.eq(page),
Mockito.anyList()))
.thenReturn(mockPage);

PageableDto<UserWithSomeOrderDetailDto> result =
service.getAllFields(page, columnName, sortingOrder, filterCriteria, TEST_EMAIL);

assertThat(result).isNotNull();
assertThat(result.getPage()).hasSize(2);
assertThat(result.getPage())
.extracting("clientName")
.containsExactly("John Doe", "Jane Smith");
Mockito.verify(employeeRepository).findByEmail(TEST_EMAIL);
Mockito.verify(employeeRepository).findTariffsInfoForEmployee(employeeId);
Mockito.verify(userRepository, Mockito.times(tariffsInfoIds.size()))
.getAllUsersByTariffsInfoId(Mockito.anyLong());
Mockito.verify(userTableRepo).findAll(filterCriteria, columnName, sortingOrder, page, userIds);
}

@Test
void getAllFieldsShouldThrowExceptionWhenEmployeeNotFound() {
Mockito.when(employeeRepository.findByEmail(TEST_EMAIL))
.thenReturn(Optional.empty());

CustomerPage page = new CustomerPage(0, 2);
String columnName = "name";
SortingOrder sortingOrder = SortingOrder.ASC;
UserFilterCriteria filterCriteria = new UserFilterCriteria();

assertThatThrownBy(() -> service.getAllFields(page, columnName, sortingOrder, filterCriteria, TEST_EMAIL))
.isInstanceOf(EntityNotFoundException.class)
.hasMessage("Employee with current id doesn't exist: ");

Mockito.verify(employeeRepository).findByEmail(TEST_EMAIL);
Mockito.verifyNoInteractions(userRepository, userTableRepo);
}

private User createTestUser(Long id, String firstName, String lastName, String email, String phone) {
User user = new User();
user.setId(id);
user.setRecipientName(firstName);
user.setRecipientSurname(lastName);
user.setRecipientEmail(email);
user.setRecipientPhone(phone);
user.setDateOfRegistration(LocalDate.now());
user.setOrders(List.of(createTestOrder()));
user.setCurrentPoints(100);
user.setViolations(1);
return user;
}

private Order createTestOrder() {
Order order = new Order();
order.setOrderDate(LocalDateTime.now().minusDays(1));
return order;
}

private Employee createTestEmployee(Long id) {
Employee employee = new Employee();
employee.setId(id);
employee.setEmail(TEST_EMAIL);
return employee;
}
}
Loading