-
Notifications
You must be signed in to change notification settings - Fork 0
Feature/db case record #12
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
Merged
Merged
Changes from all commits
Commits
Show all changes
37 commits
Select commit
Hold shift + click to select a range
cb284b1
Adeed entity CaseRecord
MartinStenhagen 2b61c2e
Adeed entity CaseNumberSequence
MartinStenhagen b5395ee
Added Flyway Migration for CaseRecord
MartinStenhagen 103109a
Added Flyway Migration for CaseNumberSequence
MartinStenhagen 0d65095
changed from year to sequence_year
MartinStenhagen 67450df
Fixed nullable mismatch
MartinStenhagen a54ae8e
Added optional = false to owner and assignedUser
MartinStenhagen 5722af8
improvements after coderabbit-feedback
MartinStenhagen 6843af7
improvements after coderabbit-feedback
MartinStenhagen df9cbde
Merge remote-tracking branch 'origin/feature/db-case-record' into fea…
MartinStenhagen fe385be
Merge branch 'main' into feature/db-case-record
MartinStenhagen 1303800
Changed import of userEntity to correspond to updated main branch and…
MartinStenhagen 3b52ea6
Removed duplicate dependencies after merge.
MartinStenhagen 4fe6a03
Removed missplaced code in CaseRecord and added Repo and Service
MartinStenhagen 92e17d9
Added Non-null validation to CaseNumberSequence constructor
MartinStenhagen d5a6168
Changes to support Registry
MartinStenhagen 65d1c64
Added validation for code
MartinStenhagen 58ade39
improvements to CaseRecord
MartinStenhagen ee1a5c0
Added CaseRecordRequestDto
MartinStenhagen 007c140
Added CaseRecordResponseDto, repositories etc
MartinStenhagen be1d8fa
Merge branch 'main' into feature/db-case-record
MartinStenhagen f09d772
Rename Flyway migration files after main merge
MartinStenhagen 95c82e7
Added getIdAsString metod to UserEntity.
MartinStenhagen e531cd4
Added exception handling
MartinStenhagen c1ec293
Added ApiExceptionHandler
MartinStenhagen fe6e029
Moved UserRepository to user-package
MartinStenhagen cdf2a85
Changed flyway migration from app_user to user_entities
MartinStenhagen 4b670d8
Added CaseRecordServiceTest
MartinStenhagen 6f519a8
Changed Exception handling to match current code in main
MartinStenhagen 4f758a1
Added CaseRecordTest
MartinStenhagen f15372d
Added CaseRecordControllerTest
MartinStenhagen 8c062de
Changed from @NotNull to @NotBlank after coderabbit feedback
MartinStenhagen 4a7940b
Changed to if (code == null || !code.matches("[A-Z]{2}")) after coder…
MartinStenhagen c9e52b4
Changed allocateNextCaseNumber to prevent race condition after codera…
MartinStenhagen 7220c77
Added tryAllocateNextCaseNumber-method after coderabbit feedback
MartinStenhagen 638c2f8
Added new tests after changed to CaseRecordService
MartinStenhagen 9cb3ddc
Added logging after coderabbit feedback
MartinStenhagen File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
71 changes: 71 additions & 0 deletions
71
src/main/java/backendlab/team4you/caserecord/CaseNumberSequence.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| package backendlab.team4you.caserecord; | ||
|
|
||
| import backendlab.team4you.registry.Registry; | ||
| import jakarta.persistence.*; | ||
| import jakarta.validation.constraints.Min; | ||
| import jakarta.validation.constraints.NotNull; | ||
|
|
||
| import java.util.Objects; | ||
|
|
||
| @Entity | ||
| @Table( | ||
| name = "case_number_sequence", | ||
| uniqueConstraints = { | ||
| @UniqueConstraint( | ||
| name = "uk_case_number_sequence_registry_year", | ||
| columnNames = {"registry_id", "sequence_year"} | ||
| ) | ||
| } | ||
| ) | ||
| public class CaseNumberSequence { | ||
|
|
||
| @Id | ||
| @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
| private Long id; | ||
|
|
||
| @ManyToOne(optional = false, fetch = FetchType.LAZY) | ||
| @JoinColumn(name = "registry_id", nullable = false) | ||
| private Registry registry; | ||
|
|
||
| @Column(name = "sequence_year",nullable = false) | ||
| private Integer year; | ||
|
|
||
| @Column(name = "last_value", nullable = false) | ||
| @NotNull | ||
| @Min(0) | ||
| private Long lastValue; | ||
|
|
||
| protected CaseNumberSequence() {} | ||
|
|
||
| public CaseNumberSequence(Registry registry, Integer year, Long lastValue) { | ||
| this.registry = Objects.requireNonNull(registry, "registry is required"); | ||
| this.year = Objects.requireNonNull(year, "year is required"); | ||
| setLastValue(lastValue); | ||
| } | ||
|
|
||
| public Long getId() { | ||
| return id; | ||
| } | ||
|
|
||
| public Registry getRegistry() { | ||
| return registry; | ||
| } | ||
|
|
||
| public Integer getYear() { | ||
| return year; | ||
| } | ||
|
|
||
| public Long getLastValue() { | ||
| return lastValue; | ||
| } | ||
|
|
||
| public void setLastValue(Long lastValue) { | ||
| if (lastValue == null) { | ||
| throw new IllegalArgumentException("lastValue is required"); | ||
| } | ||
| if (lastValue < 0) { | ||
| throw new IllegalArgumentException("lastValue must be >= 0"); | ||
| } | ||
| this.lastValue = lastValue; | ||
| } | ||
| } |
16 changes: 16 additions & 0 deletions
16
src/main/java/backendlab/team4you/caserecord/CaseNumberSequenceRepository.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| package backendlab.team4you.caserecord; | ||
|
|
||
| import backendlab.team4you.registry.Registry; | ||
| import jakarta.persistence.LockModeType; | ||
| import org.springframework.data.jpa.repository.JpaRepository; | ||
| import org.springframework.data.jpa.repository.Lock; | ||
|
|
||
| import java.util.Optional; | ||
|
|
||
| public interface CaseNumberSequenceRepository extends JpaRepository<CaseNumberSequence, Long> { | ||
|
|
||
| Optional<CaseNumberSequence> findByRegistryAndYear(Registry registry, Integer year); | ||
|
|
||
| @Lock(LockModeType.PESSIMISTIC_WRITE) | ||
| Optional<CaseNumberSequence> findWithLockByRegistryAndYear(Registry registry, Integer year); | ||
| } | ||
173 changes: 173 additions & 0 deletions
173
src/main/java/backendlab/team4you/caserecord/CaseRecord.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,173 @@ | ||
| package backendlab.team4you.caserecord; | ||
|
|
||
| import backendlab.team4you.registry.Registry; | ||
| import backendlab.team4you.user.UserEntity; | ||
| import jakarta.persistence.*; | ||
|
|
||
| import java.time.LocalDateTime; | ||
| import java.util.Objects; | ||
|
|
||
| @Entity | ||
| @Table( | ||
| name = "case_record", | ||
| uniqueConstraints = { | ||
| @UniqueConstraint(name = "uk_case_record_case_number", columnNames = "case_number") | ||
| } | ||
| ) | ||
| public class CaseRecord { | ||
|
|
||
| @Id | ||
| @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
| private Long id; | ||
|
|
||
| @Column(name = "case_number", nullable = false, length = 50, updatable = false) | ||
| private String caseNumber; | ||
|
|
||
| @ManyToOne(optional = false, fetch = FetchType.LAZY) | ||
| @JoinColumn(name = "registry_id", nullable = false) | ||
| private Registry registry; | ||
|
|
||
| @Column(nullable = false, length = 255) | ||
| private String title; | ||
|
|
||
| @Column(columnDefinition = "text") | ||
| private String description; | ||
|
|
||
| @Column(nullable = false, length = 50) | ||
| private String status; | ||
|
|
||
| @ManyToOne(optional = false, fetch = FetchType.LAZY) | ||
| @JoinColumn(name = "owner_user_id", nullable = false) | ||
| private UserEntity owner; | ||
|
|
||
| @ManyToOne(optional = false, fetch = FetchType.LAZY) | ||
| @JoinColumn(name = "assigned_user_id", nullable = false) | ||
| private UserEntity assignedUser; | ||
|
|
||
| @Column(name = "confidentiality_level", nullable = false, length = 50) | ||
| private String confidentialityLevel = "OPEN"; | ||
|
|
||
| @Column(name = "opened_at", nullable = false) | ||
| private LocalDateTime openedAt; | ||
|
|
||
| @Column(name = "created_at", nullable = false, updatable = false) | ||
| private LocalDateTime createdAt; | ||
|
|
||
| @Column(name = "updated_at") | ||
| private LocalDateTime updatedAt; | ||
|
|
||
| @Column(name = "closed_at") | ||
| private LocalDateTime closedAt; | ||
|
|
||
| protected CaseRecord() { | ||
| } | ||
|
|
||
| public CaseRecord( | ||
| Registry registry, | ||
| String title, | ||
| String description, | ||
| String status, | ||
| UserEntity owner, | ||
| UserEntity assignedUser, | ||
| String confidentialityLevel, | ||
| LocalDateTime openedAt | ||
| ) { | ||
| this.registry = Objects.requireNonNull(registry, "registry is required"); | ||
| if (title == null || title.isBlank()) { | ||
| throw new IllegalArgumentException("title is required"); | ||
| } | ||
| this.title = title.trim(); | ||
| this.description = description; | ||
| this.status = (status == null || status.isBlank()) ? "OPEN" : status.trim(); | ||
| this.owner = Objects.requireNonNull(owner, "owner is required"); | ||
| this.assignedUser = Objects.requireNonNull(assignedUser, "assignedUser is required"); | ||
| this.confidentialityLevel = | ||
| (confidentialityLevel == null || confidentialityLevel.isBlank()) | ||
| ? "OPEN" | ||
| : confidentialityLevel.trim(); | ||
|
|
||
| this.openedAt = openedAt; | ||
|
MartinStenhagen marked this conversation as resolved.
|
||
| } | ||
|
MartinStenhagen marked this conversation as resolved.
|
||
|
|
||
| @PrePersist | ||
| void onCreate() { | ||
| LocalDateTime now = LocalDateTime.now(); | ||
| if (this.caseNumber == null || this.caseNumber.isBlank()) { | ||
| throw new IllegalStateException("caseNumber must be set before persisting"); | ||
| } | ||
| this.createdAt = now; | ||
| if (this.openedAt == null) { | ||
| this.openedAt = now; | ||
| } | ||
| } | ||
|
|
||
| @PreUpdate | ||
| void onUpdate() { | ||
| this.updatedAt = LocalDateTime.now(); | ||
| } | ||
|
|
||
| public Long getId() { | ||
| return id; | ||
| } | ||
|
|
||
| public String getCaseNumber() { | ||
| return caseNumber; | ||
| } | ||
|
|
||
| public void setCaseNumber(String caseNumber) { | ||
| if (this.caseNumber != null) { | ||
| throw new IllegalStateException("caseNumber is immutable once set"); | ||
| } | ||
| if (caseNumber == null || caseNumber.isBlank()) { | ||
| throw new IllegalArgumentException("caseNumber is required"); | ||
| } | ||
| if (caseNumber.length() > 50) { | ||
| throw new IllegalArgumentException("caseNumber length must be <= 50"); | ||
| } | ||
| this.caseNumber = caseNumber; | ||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| public Registry getRegistry() { | ||
| return registry; | ||
| } | ||
|
|
||
| public String getTitle() { | ||
| return title; | ||
| } | ||
|
|
||
| public String getDescription() { | ||
| return description; | ||
| } | ||
|
|
||
| public String getStatus() { | ||
| return status; | ||
| } | ||
|
|
||
| public UserEntity getOwner() { | ||
| return owner; | ||
| } | ||
|
|
||
| public UserEntity getAssignedUser() { | ||
| return assignedUser; | ||
| } | ||
|
|
||
| public String getConfidentialityLevel() { | ||
| return confidentialityLevel; | ||
| } | ||
|
|
||
| public LocalDateTime getOpenedAt() { | ||
| return openedAt; | ||
| } | ||
|
|
||
| public LocalDateTime getCreatedAt() { | ||
| return createdAt; | ||
| } | ||
|
|
||
| public LocalDateTime getUpdatedAt() { | ||
| return updatedAt; | ||
| } | ||
|
|
||
| public LocalDateTime getClosedAt() { | ||
| return closedAt; | ||
| } | ||
| } | ||
34 changes: 34 additions & 0 deletions
34
src/main/java/backendlab/team4you/caserecord/CaseRecordController.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| package backendlab.team4you.caserecord; | ||
|
|
||
| import jakarta.validation.Valid; | ||
| 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; | ||
| import org.springframework.web.servlet.support.ServletUriComponentsBuilder; | ||
|
|
||
| import java.net.URI; | ||
|
|
||
| @RestController | ||
| @RequestMapping("/api/case-records") | ||
|
|
||
| public class CaseRecordController { | ||
| private final CaseRecordService caseRecordService; | ||
|
|
||
| public CaseRecordController(CaseRecordService caseRecordService) { | ||
| this.caseRecordService = caseRecordService; | ||
| } | ||
|
|
||
| @PostMapping | ||
| public ResponseEntity<CaseRecordResponseDto> createCaseRecord( | ||
| @Valid @RequestBody CaseRecordRequestDto requestDto) { | ||
| CaseRecordResponseDto responseDto = caseRecordService.createCaseRecord(requestDto); | ||
|
|
||
| URI location = ServletUriComponentsBuilder.fromCurrentRequest() | ||
| .path("/{id}") | ||
| .buildAndExpand(responseDto.id()) | ||
| .toUri(); | ||
| return ResponseEntity.created(location).body(responseDto); | ||
| } | ||
| } |
12 changes: 12 additions & 0 deletions
12
src/main/java/backendlab/team4you/caserecord/CaseRecordRepository.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package backendlab.team4you.caserecord; | ||
|
|
||
| import org.springframework.data.jpa.repository.JpaRepository; | ||
|
|
||
| import java.util.Optional; | ||
|
|
||
| public interface CaseRecordRepository extends JpaRepository<CaseRecord, Long> { | ||
|
|
||
| Optional<CaseRecord> findByCaseNumber(String caseNumber); | ||
|
|
||
| boolean existsByCaseNumber(String caseNumber); | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.