| 71 | | === 3. |
| | 71 | === 3. Трансакција при бришење на Person објект |
| | 72 | |
| | 73 | Оваа трансакција обезбедува безбедно и конзистентно бришење на Person објект од базата. Пред бришењето, сите извештаи поврзани со тоа лице атомски се пренасочуваат кон специјалниот „stub“ (архивен) запис, за да не останат сираци-записи и да се зачува референтниот интегритет. |
| | 74 | |
| | 75 | Целиот процес се извршува во една @Transactional операција, што гарантира дека или сите чекори ќе успеат, или ниеден (се прави rollback при грешка). Паралелно се запишува и аудит-лог со e-маилот на администраторот и бројот на префрлени извештаи, за целосна следливост. Архивниот „stub“ запис е заштитен од бришење, со што се спречуваат неконзистентни состојби. |
| | 76 | |
| | 77 | {{{ |
| | 78 | @Transactional |
| | 79 | @Override |
| | 80 | public void deletePerson(String userEmail, Long personId) { |
| | 81 | Person stub = personRepository.findByStubTrue().orElseGet(() -> { |
| | 82 | Person newStub = new Person(); |
| | 83 | newStub.setEmbg("UNIQUE-EMBG"); |
| | 84 | newStub.setName("Stub"); |
| | 85 | newStub.setSurname("Collector"); |
| | 86 | newStub.setGender(Gender.MALE); |
| | 87 | newStub.setDateOfBirth(LocalDate.of(1900, 10, 10)); |
| | 88 | newStub.setAlive(false); |
| | 89 | newStub.setAddress("N/A"); |
| | 90 | newStub.setContactPhone("N/A"); |
| | 91 | newStub.setStub(true); |
| | 92 | return personRepository.save(newStub); |
| | 93 | }); |
| | 94 | |
| | 95 | Person targetToDelete = personRepository.findById(personId).orElseThrow(() -> new PersonNotFoundException("Person with id=" + personId + " not found")); |
| | 96 | |
| | 97 | if (targetToDelete.getPersonId() == stub.getPersonId()) { |
| | 98 | throw new IllegalStateException("Archive (stub) person cannot be deleted."); |
| | 99 | } |
| | 100 | |
| | 101 | int totalReportsMoved = reportRepository.reassignReportsToStub((long) targetToDelete.getPersonId(), (long) stub.getPersonId()); |
| | 102 | String logMessage = String.format("Admin User with email %s has deleted Person: %s %s. All his %d reports were moved to stub person.", |
| | 103 | userEmail, targetToDelete.getName(), targetToDelete.getSurname(),totalReportsMoved); |
| | 104 | reportiumUserRepository.findByEmail(userEmail).ifPresent(reportiumUser -> { |
| | 105 | UserProfileLog userProfileLog = new UserProfileLog(); |
| | 106 | userProfileLog.setChangedAt(LocalDateTime.now()); |
| | 107 | userProfileLog.setChangeDescription(logMessage); |
| | 108 | userProfileLog.setUserProfile(reportiumUser.getProfile()); |
| | 109 | userProfileLogRepository.save(userProfileLog); |
| | 110 | }); |
| | 111 | personRepository.delete(targetToDelete); |
| | 112 | } |
| | 113 | |
| | 114 | *** Методот reassignReportsToStub |
| | 115 | {{{ |
| | 116 | @Modifying(clearAutomatically = true, flushAutomatically = true) |
| | 117 | @Query(value = """ |
| | 118 | UPDATE Report r |
| | 119 | SET r.person.personId = :stub_person_id |
| | 120 | WHERE r.person.personId = :target_to_delete_person_id |
| | 121 | """) |
| | 122 | int reassignReportsToStub(@Param("target_to_delete_person_id") Long targetId, |
| | 123 | @Param("stub_person_id") Long stubId); |
| | 124 | }}} |
| | 125 | }}} |