Skip to content
Merged
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
3 changes: 3 additions & 0 deletions lombok.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Copy the Qualifier and Value annotations from the instance variables to the constructor
lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Qualifier
lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Value
2 changes: 2 additions & 0 deletions src/main/java/com/example/ecm/DemoApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@ApiResponse(responseCode = "200", description = "Hello World")
@EnableScheduling
@SpringBootApplication
public class DemoApplication {

Expand Down
16 changes: 16 additions & 0 deletions src/main/java/com/example/ecm/config/VotingConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.example.ecm.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

@Configuration
public class VotingConfig {

@Bean("votingFinisherScheduler")
public ScheduledExecutorService scheduledExecutorService() {
return Executors.newScheduledThreadPool(10);
}
}
20 changes: 12 additions & 8 deletions src/main/java/com/example/ecm/controller/DocumentController.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@

import com.example.ecm.dto.requests.CreateDocumentRequest;
import com.example.ecm.dto.requests.CreateDocumentVersionRequest;
import com.example.ecm.dto.requests.CreateSignatureRequestRequest;
import com.example.ecm.dto.responses.CreateDocumentResponse;
import com.example.ecm.dto.responses.CreateDocumentVersionResponse;
import com.example.ecm.dto.responses.CreateSignatureRequestResponse;
import com.example.ecm.security.UserPrincipal;
import com.example.ecm.service.DocumentService;
import com.example.ecm.service.SignatureService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

import java.util.List;
Expand All @@ -23,6 +28,7 @@ public class DocumentController {

// Экземпляр DocumentService для обработки бизнес-логики, связанной с документами.
private final DocumentService documentService;
private final SignatureService signatureService;

/**
* POST-метод для создания нового документа.
Expand Down Expand Up @@ -77,20 +83,18 @@ public ResponseEntity<Void> deleteDocument(@PathVariable Long id) {
*/

@GetMapping
public List<CreateDocumentResponse> getAllDocument() {
return documentService.getAllDocuments();
public ResponseEntity<List<CreateDocumentResponse>> getAllDocument() {
return ResponseEntity.ok(documentService.getAllDocuments());
}

/**
* POST-метод для подписания документа по его ID.
*
* @param id Идентификатор документа, который нужно подписать.
* @param signature Объект запроса, содержащий данные подписи.
*/
/*
@PostMapping("/{id}")
public void signDocument(@PathVariable Long id, @RequestBody CreateSignatureRequest signature) {
documentService.signDocument(id, signature);

@PostMapping("/{id}/send")
public ResponseEntity<CreateSignatureRequestResponse> sendToSign(@PathVariable Long id, @RequestBody CreateSignatureRequestRequest signatureRequest, @AuthenticationPrincipal UserPrincipal userPrincipal) {
return ResponseEntity.ok(signatureService.sendToSign(id, signatureRequest, userPrincipal));
}
*/
}
26 changes: 26 additions & 0 deletions src/main/java/com/example/ecm/controller/VotingController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.example.ecm.controller;

import com.example.ecm.dto.requests.StartVotingRequest;
import com.example.ecm.dto.responses.StartVotingResponse;
import com.example.ecm.service.VotingService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
@RequestMapping("/votings")
public class VotingController {

private final VotingService votingService;

@PostMapping
public ResponseEntity<StartVotingResponse> startVoting(@Valid @RequestBody StartVotingRequest request) {
return ResponseEntity.ok(votingService.startVoting(request));
}

}
33 changes: 33 additions & 0 deletions src/main/java/com/example/ecm/dto/requests/StartVotingRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.example.ecm.dto.requests;

import jakarta.validation.constraints.Future;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import lombok.Data;

import java.time.LocalDateTime;
import java.util.List;

@Data
public class StartVotingRequest {

@NotNull(message = "participantIds cannot be null")
private List<Long> participantIds;

@NotNull(message = "documentId cannot be null")
private Long documentId;

@NotNull(message = "documentVersionId cannot be null")
private Long documentVersionId;

@Min(value = 0, message = "approvalThreshold must be between 0 and 100")
@Max(value = 100, message = "approvalThreshold must be between 0 and 100")
@NotNull(message = "approvalThreshold cannot be null")
private Float approvalThreshold;

@Future(message = "deadline cannot be in the past")
@NotNull(message = "approvalThreshold cannot be null")
private LocalDateTime deadline;

}
16 changes: 16 additions & 0 deletions src/main/java/com/example/ecm/dto/requests/VoteRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.example.ecm.dto.requests;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class VoteRequest {

@NotBlank(message = "decision cannot be blank")
private String decision;
@NotNull(message = "documentVersionId cannot be null")
private Long documentVersionId;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.example.ecm.dto.responses;

import lombok.Data;

import java.time.LocalDateTime;
import java.util.List;

@Data
public class StartVotingResponse {

private List<CreateUserResponse> participants;

private CreateDocumentVersionResponse documentVersion;

private Float approvalThreshold;

private LocalDateTime deadline;

private String status;
}
38 changes: 38 additions & 0 deletions src/main/java/com/example/ecm/mapper/VotingMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.example.ecm.mapper;

import com.example.ecm.dto.requests.StartVotingRequest;
import com.example.ecm.dto.responses.StartVotingResponse;
import com.example.ecm.model.DocumentVersion;
import com.example.ecm.model.Voting;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Component
@RequiredArgsConstructor
public class VotingMapper {
private final UserMapper userMapper;
private final DocumentVersionMapper documentVersionMapper;

public Voting toVoting(StartVotingRequest request, DocumentVersion documentVersion, String status) {
Voting voting = new Voting();
voting.setDocumentVersion(documentVersion);
voting.setApprovalThreshold(request.getApprovalThreshold());
voting.setDeadline(request.getDeadline());
voting.setCreatedAt(LocalDateTime.now());
voting.setStatus(status);
return voting;
}

public StartVotingResponse toStartVotingResponse(Voting voting) {
StartVotingResponse response = new StartVotingResponse();
response.setParticipants(voting.getSignatureRequests().stream().map(r -> userMapper.toCreateUserResponse(r.getUserTo())).toList());
response.setDocumentVersion(documentVersionMapper.toCreateDocumentVersionResponse(voting.getDocumentVersion()));
response.setDeadline(voting.getDeadline());
response.setApprovalThreshold(voting.getApprovalThreshold());
response.setStatus(voting.getStatus());

return response;
}
}
10 changes: 4 additions & 6 deletions src/main/java/com/example/ecm/model/SignatureRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,13 @@ public class SignatureRequest {
@JoinColumn(name = "user_id_to")
private User userTo;

@ManyToOne
@JoinColumn(name = "voting_id")
private Voting voting;

@ManyToOne
@JoinColumn(name = "document_version_id")
private DocumentVersion documentVersion;

/**
* Флаг, который обозначает была ли поставлена подпись.
* null - заявка пока не была обработана
* false - документ был отклонен
* true - документ был подписан
*/
private String status;
}
49 changes: 49 additions & 0 deletions src/main/java/com/example/ecm/model/Voting.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.example.ecm.model;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;

import java.time.LocalDateTime;
import java.util.List;

@Getter
@Setter
@Entity
@Table(name = "votings")
public class Voting {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne
@JoinColumn(name = "document_version_id")
private DocumentVersion documentVersion;

@OneToMany(mappedBy = "voting")
private List<SignatureRequest> signatureRequests;

@Column(nullable = false)
private String status;

@Column(nullable = false)
private Float approvalThreshold;

private Float currentApprovalRate;

@Column(nullable = false)
private LocalDateTime createdAt;

@Column(nullable = false)
private LocalDateTime deadline;

}
12 changes: 12 additions & 0 deletions src/main/java/com/example/ecm/repository/VotingRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.example.ecm.repository;

import com.example.ecm.model.Voting;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface VotingRepository extends JpaRepository<Voting, Long> {
List<Voting> findByStatus(String status);
}
55 changes: 0 additions & 55 deletions src/main/java/com/example/ecm/service/DocumentService.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package com.example.ecm.service;

import com.example.ecm.dto.requests.CreateDocumentVersionRequest;
import com.example.ecm.dto.requests.CreateSignatureRequestRequest;
import com.example.ecm.dto.requests.SetValueRequest;
import com.example.ecm.dto.responses.CreateDocumentVersionResponse;
import com.example.ecm.dto.responses.CreateSignatureRequestResponse;
import com.example.ecm.exception.ForbiddenException;
import com.example.ecm.exception.ServerException;
import com.example.ecm.mapper.*;
import com.example.ecm.model.*;
Expand All @@ -15,13 +12,11 @@
import com.example.ecm.dto.responses.CreateDocumentResponse;
import com.example.ecm.exception.NotFoundException;
import com.example.ecm.mapper.DocumentMapper;
import com.example.ecm.mapper.SignatureMapper;
import com.example.ecm.model.Document;
import com.example.ecm.model.DocumentType;
import com.example.ecm.model.User;
import com.example.ecm.repository.DocumentRepository;
import com.example.ecm.repository.DocumentTypeRepository;
import com.example.ecm.security.UserPrincipal;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

Expand All @@ -46,11 +41,6 @@ public class DocumentService {
private final DocumentVersionRepository documentVersionRepository;
private final AttributeRepository attributeRepository;
private final ValueRepository valueRepository;
private final SignatureRequestRepository signatureRequestRepository;
private final SignatureMapper signatureMapper;

private final UserService userService;


/**
* Создает новый документ.
Expand Down Expand Up @@ -199,49 +189,4 @@ private void setValues(List<SetValueRequest> values, DocumentVersion documentVer
valueRepository.save(value);
}
}

/**
* Добавляет подпись в документ.
*
* @param id идентификатор документа
*/

public CreateSignatureRequestResponse sendToSign(Long id, CreateSignatureRequestRequest request, UserPrincipal currentUser) {
Document document = documentRepository.findById(id)
.orElseThrow(() -> new NotFoundException("Document with id: " + id +" not found"));

DocumentVersion documentVersion = document.getDocumentVersions().stream()
.filter(v -> v.getVersionId().equals(request.getDocumentVersionId()))
.findFirst().orElseThrow(() -> new NotFoundException("Document version with id: " + id +" not found"));

User user = userRepository.findById(id).orElseThrow(() -> new NotFoundException("User with id: " + id + " not found"));

if (!currentUser.getId().equals(document.getUser().getId()) || !currentUser.isAdmin()) {
throw new ForbiddenException("You have no permission to send this document");
}

Signature signature = signatureMapper.toSignature(document, documentVersion);

documentVersion.getSignatures().add(signature);

documentVersionRepository.save(documentVersion);

SignatureRequest signatureRequest = new SignatureRequest();
signatureRequest.setUserTo(user);
signatureRequest.setDocumentVersion(documentVersion);
signatureRequest.setStatus("PENDING");

signatureRequest = signatureRequestRepository.save(signatureRequest);

return signatureMapper.toCreateSignatureRequestResponse(signatureRequest);
}


private User getUser(Long id) {
return userService.findById(id).orElseThrow(() -> new NotFoundException("No such user"));
}

private DocumentType getDocumentType(Long id) {
return documentTypeRepository.findById(id).orElseThrow(() -> new NotFoundException("No such document type"));
}
}
Loading