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 | }}} |