Commit 772e390a authored by Rajendra Kishor Rahu's avatar Rajendra Kishor Rahu
Browse files

Admin config structure build

Showing with 599 additions and 31 deletions
+599 -31
......@@ -119,6 +119,11 @@
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
</dependencies>
<build>
......
package org.upsmf.grievance.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.upsmf.grievance.dto.TicketCouncilDto;
import org.upsmf.grievance.dto.TicketDepartmentDto;
import org.upsmf.grievance.dto.TicketRequest;
import org.upsmf.grievance.dto.TicketUserTypeDto;
import org.upsmf.grievance.exception.CustomException;
import org.upsmf.grievance.exception.DataUnavailabilityException;
import org.upsmf.grievance.exception.TicketException;
import org.upsmf.grievance.model.Ticket;
import org.upsmf.grievance.model.reponse.Response;
import org.upsmf.grievance.service.TicketCouncilService;
import org.upsmf.grievance.service.TicketDepartmentService;
import org.upsmf.grievance.service.TicketUserTypeService;
import org.upsmf.grievance.util.ErrorCode;
import javax.validation.Valid;
import java.util.List;
@Slf4j
@RestController
@RequestMapping(path = "/api/admin")
public class AdminController {
@Autowired
private TicketUserTypeService ticketUserTypeService;
@Autowired
private TicketCouncilService ticketCouncilService;
@Autowired
private TicketDepartmentService ticketDepartmentService;
/**
* @param ticketUserTypeDto
* @return
*/
@PostMapping("/ticket/userType/save")
public ResponseEntity<Response> saveUserType(@Valid @RequestBody TicketUserTypeDto ticketUserTypeDto) {
try {
ticketUserTypeService.save(ticketUserTypeDto);
} catch (CustomException e) {
log.error("Error in while creating ticket user type - at controller");
throw new TicketException(e.getMessage(), ErrorCode.TKT_001, "Error while trying to create ticket user type");
} catch (Exception e) {
log.error("Internal server error while creating ticket user type", e);
throw new TicketException("Internal server error while creating ticket user type", ErrorCode.TKT_002, e.getMessage());
}
Response response = new Response(HttpStatus.OK.value(), "Ticket user type has been created successfully");
return new ResponseEntity<>(response, HttpStatus.OK);
}
/**
* @param ticketUserTypeDto
* @return
*/
@PostMapping("/ticket/userType/update")
public ResponseEntity<Response> updateUserType(@Valid @RequestBody TicketUserTypeDto ticketUserTypeDto) {
try {
ticketUserTypeService.update(ticketUserTypeDto);
} catch (CustomException e) {
log.error("Error in while updating ticket user type - at controller");
throw new TicketException(e.getMessage(), ErrorCode.TKT_001, "Error while trying to update ticket user type");
} catch (Exception e) {
log.error("Internal server error while updating ticket user type", e);
throw new TicketException("Internal server error while updating update user type", ErrorCode.TKT_002, e.getMessage());
}
Response response = new Response(HttpStatus.OK.value(), "Ticket user type has been updated successfully");
return new ResponseEntity<>(response, HttpStatus.OK);
}
/**
* @param ticketUserTypeDto
* @return
*/
@PostMapping("/ticket/userType/updateActivation")
public ResponseEntity<Response> updateUserTypeActivation(@RequestBody TicketUserTypeDto ticketUserTypeDto) {
try {
ticketUserTypeService.updateUserTypeActivation(ticketUserTypeDto);
} catch (CustomException e) {
log.error("Error in while updating ticket user type status- at controller");
throw new TicketException(e.getMessage(), ErrorCode.TKT_001, "Error while trying to update ticket user type status");
} catch (Exception e) {
log.error("Internal server error while updating ticket user type status", e);
throw new TicketException("Internal server error while updating update user type status", ErrorCode.TKT_002, e.getMessage());
}
Response response = new Response(HttpStatus.OK.value(), "Ticket user type status has been updated successfully");
return new ResponseEntity<>(response, HttpStatus.OK);
}
/**
* @return
*/
@GetMapping("/ticket/userType/searchAll")
public ResponseEntity<List<TicketUserTypeDto>> searchAllUserType() {
try {
List<TicketUserTypeDto> ticketUserTypeList = ticketUserTypeService.findAllUserType();
return new ResponseEntity<>(ticketUserTypeList, HttpStatus.OK);
} catch (CustomException e) {
log.error("Error in while fetching all ticket user type - at controller");
throw new TicketException(e.getMessage(), ErrorCode.TKT_001, "Error while fetching all ticket user type");
} catch (Exception e) {
log.error("Internal server error while fetching all ticket user type", e);
throw new TicketException("Internal server error while fetching all ticket user type", ErrorCode.TKT_002, e.getMessage());
}
}
/**
* @param ticketCouncilDto
* @return
*/
@PostMapping("/ticket/council/save")
public ResponseEntity<Response> ticketCouncilSave(@Valid @RequestBody TicketCouncilDto ticketCouncilDto) {
try {
ticketCouncilService.save(ticketCouncilDto);
} catch (CustomException e) {
log.error("Error in while creating ticket council - at controller");
throw new TicketException(e.getMessage(), ErrorCode.TKT_001, "Error while trying to create ticket council");
} catch (Exception e) {
log.error("Internal server error while creating ticket council", e);
throw new TicketException("Internal server error while creating ticket council", ErrorCode.TKT_002, e.getMessage());
}
Response response = new Response(HttpStatus.OK.value(), "Ticket council has been created successfully");
return new ResponseEntity<>(response, HttpStatus.OK);
}
/**
* @param ticketCouncilDto
* @return
*/
@PostMapping("/ticket/council/update")
public ResponseEntity<Response> ticketCouncilUpdate(@Valid @RequestBody TicketCouncilDto ticketCouncilDto) {
try {
ticketCouncilService.update(ticketCouncilDto);
} catch (CustomException e) {
log.error("Error in while updating ticket council - at controller");
throw new TicketException(e.getMessage(), ErrorCode.TKT_001, "Error while trying to update ticket council");
} catch (Exception e) {
log.error("Internal server error while updating ticket council", e);
throw new TicketException("Internal server error while updating ticket council", ErrorCode.TKT_002, e.getMessage());
}
Response response = new Response(HttpStatus.OK.value(), "Ticket council has been created successfully");
return new ResponseEntity<>(response, HttpStatus.OK);
}
/**
* @return
*/
@GetMapping("/ticket/council/searchAll")
public ResponseEntity<List<TicketCouncilDto>> searchAllCouncil() {
try {
List<TicketCouncilDto> ticketCouncilDtoList = ticketCouncilService.findAllCouncil();
return new ResponseEntity<>(ticketCouncilDtoList, HttpStatus.OK);
} catch (CustomException e) {
log.error("Error in while fetching all ticket council data- at controller");
throw new TicketException(e.getMessage(), ErrorCode.TKT_001, "Error while fetching all ticket council data");
} catch (Exception e) {
log.error("Internal server error while fetching all ticket council data", e);
throw new TicketException("Internal server error while fetching all ticket council data", ErrorCode.TKT_002, e.getMessage());
}
}
/**
* @param ticketCouncilDto
* @return
*/
@PostMapping("/ticket/council/updateActivation")
public ResponseEntity<Response> updateTicketCouncilActivation(@RequestBody TicketCouncilDto ticketCouncilDto) {
try {
ticketCouncilService.updateTicketCouncilActivation(ticketCouncilDto);
} catch (CustomException e) {
log.error("Error in while updating ticket council activation status- at controller");
throw new TicketException(e.getMessage(), ErrorCode.TKT_001, "Error while trying to update ticket council activation status");
} catch (Exception e) {
log.error("Internal server error while updating ticket council activation status", e);
throw new TicketException("Internal server error while updating update council activation status", ErrorCode.TKT_002, e.getMessage());
}
Response response = new Response(HttpStatus.OK.value(), "Ticket council activation status has been updated successfully");
return new ResponseEntity<>(response, HttpStatus.OK);
}
/**
* @param ticketDepartmentDto
* @return
*/
@PostMapping("/ticket/department/save")
public ResponseEntity<Response> ticketDepartmentSave(@Valid @RequestBody TicketDepartmentDto ticketDepartmentDto) {
try {
ticketDepartmentService.save(ticketDepartmentDto);
} catch (CustomException e) {
log.error("Error in while creating ticket department - at controller");
throw new TicketException(e.getMessage(), ErrorCode.TKT_001, "Error while trying to create ticket department");
} catch (Exception e) {
log.error("Internal server error while creating ticket department", e);
throw new TicketException("Internal server error while creating ticket department", ErrorCode.TKT_002, e.getMessage());
}
Response response = new Response(HttpStatus.OK.value(), "Ticket department has been created successfully");
return new ResponseEntity<>(response, HttpStatus.OK);
}
/**
* @param ticketDepartmentDto
* @return
*/
@PostMapping("/ticket/department/update")
public ResponseEntity<Response> ticketDepartmentUpdate(@Valid @RequestBody TicketDepartmentDto ticketDepartmentDto) {
try {
ticketDepartmentService.update(ticketDepartmentDto);
} catch (CustomException e) {
log.error("Error in while updating ticket department - at controller");
throw new TicketException(e.getMessage(), ErrorCode.TKT_001, "Error while trying to update ticket department");
} catch (Exception e) {
log.error("Internal server error while updating ticket department", e);
throw new TicketException("Internal server error while updating ticket department", ErrorCode.TKT_002, e.getMessage());
}
Response response = new Response(HttpStatus.OK.value(), "Ticket department has been updated successfully");
return new ResponseEntity<>(response, HttpStatus.OK);
}
/**
* @return
*/
@GetMapping("/ticket/department/searchAll")
public ResponseEntity<List<TicketDepartmentDto>> searchAllTicketDepartment() {
try {
List<TicketDepartmentDto> ticketDepartmentDtoList = ticketDepartmentService.findAllTicketDepartment();
return new ResponseEntity<>(ticketDepartmentDtoList, HttpStatus.OK);
} catch (CustomException e) {
log.error("Error in while fetching all ticket department data- at controller");
throw new TicketException(e.getMessage(), ErrorCode.TKT_001, "Error while fetching all ticket department data");
} catch (Exception e) {
log.error("Internal server error while fetching all ticket department data", e);
throw new TicketException("Internal server error while fetching all ticket department data", ErrorCode.TKT_002, e.getMessage());
}
}
@PostMapping("/ticket/department/updateActivation")
public ResponseEntity<Response> updateTicketDepartmentActivation(@RequestBody TicketDepartmentDto ticketDepartmentDto) {
try {
ticketDepartmentService.updateTicketDepartmentActivation(ticketDepartmentDto);
} catch (CustomException e) {
log.error("Error in while updating ticket department activation status- at controller");
throw new TicketException(e.getMessage(), ErrorCode.TKT_001, "Error while trying to update ticket department activation status");
} catch (Exception e) {
log.error("Internal server error while updating ticket department activation status", e);
throw new TicketException("Internal server error while updating update department activation status", ErrorCode.TKT_002, e.getMessage());
}
Response response = new Response(HttpStatus.OK.value(), "Ticket department activation status has been updated successfully");
return new ResponseEntity<>(response, HttpStatus.OK);
}
}
......@@ -12,7 +12,7 @@ import org.upsmf.grievance.dto.UpdateUserDto;
import org.upsmf.grievance.dto.UserResponseDto;
import org.upsmf.grievance.exception.CustomException;
import org.upsmf.grievance.exception.UserException;
import org.upsmf.grievance.model.Department;
import org.upsmf.grievance.model.UserDepartment;
import org.upsmf.grievance.model.User;
import org.upsmf.grievance.service.IntegrationService;
import org.upsmf.grievance.util.ErrorCode;
......@@ -58,31 +58,47 @@ public class UserController {
}
}
private ResponseEntity<UserResponseDto> createUserResponse(User body) {
Map<String, List<String>> attributes = new HashMap<>();
attributes.put("Role", Arrays.asList(body.getRoles()));
List<String> department = new ArrayList<>();
if(body.getDepartment() != null && !body.getDepartment().isEmpty()) {
for(Department depart : body.getDepartment()) {
department.add(depart.getDepartmentName());
}
private ResponseEntity<UserResponseDto> createUserResponse(User user) {
// Map<String, List<String>> attributes = new HashMap<>();
// attributes.put("Role", Arrays.asList(body.getRoles()));
// List<String> department = new ArrayList<>();
// if(body.getUserDepartment() != null && !body.getUserDepartment().isEmpty()) {
// for(UserDepartment depart : body.getUserDepartment()) {
// department.add(depart.getDepartmentName());
// }
// }
// attributes.put("departmentName", department);
// attributes.put("phoneNumber", Arrays.asList(body.getPhoneNumber()));
Map<String, Object> attributeMap = new HashMap<>();
attributeMap.put("phoneNumber", user.getPhoneNumber());
attributeMap.put("role", user.getRoles());
UserDepartment userDepartment = user.getUserDepartment();
if (userDepartment != null) {
attributeMap.put("departmentId", userDepartment.getDepartmentId());
attributeMap.put("departmentName", userDepartment.getDepartmentName());
attributeMap.put("councilId", userDepartment.getCouncilId());
attributeMap.put("councilName", userDepartment.getCouncilName());
}
attributes.put("departmentName", department);
attributes.put("phoneNumber", Arrays.asList(body.getPhoneNumber()));
boolean enabled = false;
if(body.getStatus() == 1) {
if(user.getStatus() == 1) {
enabled = true;
}
UserResponseDto userResponseDto = UserResponseDto.builder()
.email(body.getEmail())
.emailVerified(body.isEmailVerified())
.email(user.getEmail())
.emailVerified(user.isEmailVerified())
.enabled(enabled)
.firstName(body.getFirstName())
.lastName(body.getLastname())
.id(body.getId())
.keycloakId(body.getKeycloakId())
.username(body.getUsername())
.attributes(attributes)
.firstName(user.getFirstName())
.lastName(user.getLastname())
.id(user.getId())
.keycloakId(user.getKeycloakId())
.username(user.getUsername())
.attributes(attributeMap)
.build();
return ResponseEntity.ok().body(userResponseDto);
}
......
......@@ -38,4 +38,6 @@ public class SearchRequest {
private Map<String, String> sort;
private Long ticketUserTypeId;
}
package org.upsmf.grievance.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.*;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonInclude(JsonInclude.Include.NON_NULL)
public class TicketCouncilDto {
private Long ticketCouncilId;
@NotBlank(message = "Ticket council name is required")
private String ticketCouncilName;
private Boolean status;
private List<TicketDepartmentDto> ticketDepartmentDtoList;
}
package org.upsmf.grievance.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.*;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonInclude(JsonInclude.Include.NON_NULL)
public class TicketDepartmentDto {
private Long ticketDepartmentId;
@NotBlank(message = "Ticket department name is required")
private String ticketDepartmentName;
@NotNull(message = "Ticket council id is required")
private Long ticketCouncilId;
private Boolean status;
}
......@@ -17,12 +17,15 @@ public class TicketRequest {
private String lastName;
private String email;
private String phone;
private RequesterType userType;
// private RequesterType userType;
private String cc;
private String requestType;
private String description;
private List<String> attachmentUrls;
private String otp;
private String mobileOtp;
private Long ticketUserTypeId;
private Long ticketCouncilId;
private Long ticketDepartmentId;
}
package org.upsmf.grievance.dto;
import lombok.*;
import javax.validation.constraints.*;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class TicketUserTypeDto {
private Long userTypeId;
@NotBlank(message = "Ticket user type name is required")
private String userTypeName;
private Boolean status;
}
package org.upsmf.grievance.dto;
import lombok.*;
import org.upsmf.grievance.model.Department;
import org.upsmf.grievance.model.UserDepartment;
@Getter
@Setter
......@@ -18,7 +18,7 @@ public class UserDto {
private String email;
private String password;
private boolean emailVerified;
private Department department;
private UserDepartment userDepartment;
private String[] roles;
}
......@@ -29,5 +29,7 @@ public class UserResponseDto implements Serializable {
private boolean enabled;
private Map<String, List<String>> attributes;
// private Map<String, List<String>> attributes;
private Map<String, Object> attributes;
}
package org.upsmf.grievance.exception;
import org.upsmf.grievance.util.ErrorCode;
public class InvalidDataException extends CustomException {
public InvalidDataException(String message) {
super(message);
}
public InvalidDataException(String message, String description) {
super(message, description);
}
public InvalidDataException(String message, ErrorCode errorCode) {
super(message, errorCode);
}
public InvalidDataException(String message, ErrorCode errorCode, String description) {
super(message, errorCode, description);
}
}
......@@ -17,6 +17,7 @@ import org.upsmf.grievance.exception.runtime.InvalidRequestException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
@ControllerAdvice
......@@ -24,6 +25,11 @@ public class ExceptionHandler4xxController {
private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionHandler4xxController.class);
/**
* It generates all error list that occurs when argument validation fails.
* @param exception
* @return
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String, List<String>>> handleValidationErrors(MethodArgumentNotValidException exception) {
......@@ -34,6 +40,27 @@ public class ExceptionHandler4xxController {
return new ResponseEntity<>(getErrorsMap(errors), new HttpHeaders(), HttpStatus.BAD_REQUEST);
}
// /**
// * Maintain error message uniformity with custom exception
// * @param exception
// * @return
// */
// @ExceptionHandler(MethodArgumentNotValidException.class)
// public ResponseEntity<Map<String, Object>> handleValidationErrors(MethodArgumentNotValidException exception) {
//
// List<String> exceptionMessage = exception.getBindingResult().getFieldErrors().stream()
// .map(FieldError::getDefaultMessage)
// .collect(Collectors.toList());
//
// Map<String, Object> errorResponse = new HashMap<>();
//
// errorResponse.put("error_message", exceptionMessage);
//
// return new ResponseEntity<>(errorResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST);
// }
/**
* Exception handler for Invalid request exception
* @param e
......
......@@ -23,6 +23,7 @@ public class AssigneeTicketAttachment {
@Column(name = "user_id", nullable = false)
private String userId;
@Lob
@Column(name = "attachment_url", nullable = false)
private String attachment_url;
}
......@@ -20,6 +20,7 @@ public class RaiserTicketAttachment {
@Column(name = "ticket_id", nullable = false)
private Long ticketId;
@Lob
@Column(name = "attachment_url", nullable = false)
private String attachment_url;
}
......@@ -38,9 +38,6 @@ public class Ticket {
@Column(name = "requester_email")
private String email;
@Column(name = "requester_type")
private RequesterType requesterType;
@Column(name = "assigned_to_id")
private String assignedToId;
......@@ -81,7 +78,7 @@ public class Ticket {
private TicketStatus status = TicketStatus.OPEN;
@Column(name = "request_type")
private String requestType;
private String requestType; //TODO: rkr: userDepartment replace with configurable userDepartment
@Column(name = "priority")
private TicketPriority priority = TicketPriority.LOW;
......@@ -104,4 +101,13 @@ public class Ticket {
@OneToMany(targetEntity = AssigneeTicketAttachment.class, mappedBy = "ticketId", fetch = FetchType.EAGER)
@Fetch(value = FetchMode.SUBSELECT)
private List<AssigneeTicketAttachment> assigneeTicketAttachment;
@ManyToOne(targetEntity = TicketUserType.class, fetch = FetchType.EAGER)
private TicketUserType ticketUserType;
@ManyToOne(targetEntity = TicketCouncil.class, fetch = FetchType.EAGER)
private TicketCouncil ticketCouncil;
@ManyToOne(targetEntity = TicketDepartment.class, fetch = FetchType.EAGER)
private TicketDepartment ticketDepartment;
}
package org.upsmf.grievance.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import javax.persistence.*;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity
@Table(name = "ticket_council")
public class TicketCouncil {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "ticket_council_name", unique = true)
private String ticketCouncilName;
@Column(name = "status")
private Boolean status;
@OneToMany(targetEntity = TicketDepartment.class, mappedBy = "ticketCouncilId", fetch = FetchType.EAGER)
@Fetch(value = FetchMode.SUBSELECT)
private List<TicketDepartment> ticketDepartments;
}
package org.upsmf.grievance.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import javax.persistence.*;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity
@Table(name = "ticket_department")
public class TicketDepartment {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "ticket_department_name", unique = false)
private String ticketDepartmentName;
@Column(name = "ticket_council_id", nullable = false)
private Long ticketCouncilId;
@Column(name = "status")
private Boolean status;
// @OneToMany //(targetEntity = UserDepartment.class, mappedBy = "ticket_department_id", fetch = FetchType.EAGER)
// @Fetch(value = FetchMode.SUBSELECT)
// private List<User> user;
}
package org.upsmf.grievance.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity
@Table(name = "ticket_user_type")
public class TicketUserType {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "user_type_name", unique = true)
private String userTypeName;
@Column(name = "status")
private Boolean status;
}
......@@ -43,9 +43,12 @@ public class User {
private String[] roles;
@OneToMany(targetEntity = Department.class, mappedBy = "userId", fetch = FetchType.EAGER)
@Fetch(value = FetchMode.SUBSELECT)
private List<Department> department;
// @OneToMany(targetEntity = UserDepartment.class, mappedBy = "userId", fetch = FetchType.EAGER)
// @Fetch(value = FetchMode.SUBSELECT)
// private List<UserDepartment> userDepartment;
@ManyToOne(targetEntity = UserDepartment.class, fetch = FetchType.EAGER)
private UserDepartment userDepartment;
@OneToMany(fetch = FetchType.EAGER)
@Fetch(value = FetchMode.SUBSELECT)
......
package org.upsmf.grievance.model;
import lombok.*;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import javax.persistence.*;
import java.util.List;
@Entity
@Table(name = "department")
@Table(name = "userDepartment")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString
public class Department {
public class UserDepartment {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "department_Id")
private Long departmentId;
@Column(name = "department_name", nullable = false)
private String departmentName;
@Column(name = "user_id", nullable = false)
private Long userId;
@Column(name = "council_Id")
private Long councilId;
@Column(name = "council_name")
private String councilName;
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment