autocomit
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
package com.ldpv2.controller;
|
||||
|
||||
import com.ldpv2.domain.enums.ApplicationStatus;
|
||||
import com.ldpv2.dto.request.AddContactToApplicationRequest;
|
||||
import com.ldpv2.dto.request.CreateApplicationRequest;
|
||||
import com.ldpv2.dto.request.UpdateApplicationRequest;
|
||||
import com.ldpv2.dto.response.ApplicationContactResponse;
|
||||
import com.ldpv2.dto.response.ApplicationResponse;
|
||||
import com.ldpv2.service.ApplicationService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
@@ -18,6 +20,7 @@ import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@RestController
|
||||
@@ -118,4 +121,31 @@ public class ApplicationController {
|
||||
applicationService.delete(id);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
// ========== CONTACTS MANAGEMENT ==========
|
||||
|
||||
@GetMapping("/{applicationId}/contacts")
|
||||
@Operation(summary = "Get application contacts", description = "Get all contacts for an application")
|
||||
public ResponseEntity<List<ApplicationContactResponse>> getContacts(@PathVariable UUID applicationId) {
|
||||
List<ApplicationContactResponse> response = applicationService.getApplicationContacts(applicationId);
|
||||
return ResponseEntity.ok(response);
|
||||
}
|
||||
|
||||
@PostMapping("/{applicationId}/contacts")
|
||||
@Operation(summary = "Add contact to application", description = "Associate a contact with an application")
|
||||
public ResponseEntity<ApplicationContactResponse> addContact(
|
||||
@PathVariable UUID applicationId,
|
||||
@Valid @RequestBody AddContactToApplicationRequest request) {
|
||||
ApplicationContactResponse response = applicationService.addContact(applicationId, request.getContactId());
|
||||
return new ResponseEntity<>(response, HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{applicationId}/contacts/{contactId}")
|
||||
@Operation(summary = "Remove contact from application", description = "Remove a contact from an application")
|
||||
public ResponseEntity<Void> removeContact(
|
||||
@PathVariable UUID applicationId,
|
||||
@PathVariable UUID contactId) {
|
||||
applicationService.removeContact(applicationId, contactId);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Application entity representing software systems
|
||||
@@ -17,7 +19,7 @@ import java.time.LocalDate;
|
||||
@Table(name = "application")
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@EqualsAndHashCode(callSuper = true, exclude = {"applicationContacts"})
|
||||
public class Application extends BaseEntity {
|
||||
|
||||
@Column(nullable = false, length = 255)
|
||||
@@ -39,4 +41,18 @@ public class Application extends BaseEntity {
|
||||
|
||||
@Column(name = "end_of_support_date")
|
||||
private LocalDate endOfSupportDate;
|
||||
|
||||
@OneToMany(mappedBy = "application", cascade = CascadeType.ALL, orphanRemoval = true)
|
||||
private Set<ApplicationContact> applicationContacts = new HashSet<>();
|
||||
|
||||
public void addContact(Contact contact) {
|
||||
ApplicationContact appContact = new ApplicationContact();
|
||||
appContact.setApplication(this);
|
||||
appContact.setContact(contact);
|
||||
applicationContacts.add(appContact);
|
||||
}
|
||||
|
||||
public void removeContact(Contact contact) {
|
||||
applicationContacts.removeIf(ac -> ac.getContact().equals(contact));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.ldpv2.domain.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Junction entity linking Applications to Contacts
|
||||
*/
|
||||
@Data
|
||||
@Entity
|
||||
@Table(name = "application_contact")
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ApplicationContact implements Serializable {
|
||||
|
||||
@EmbeddedId
|
||||
private ApplicationContactId id = new ApplicationContactId();
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@MapsId("applicationId")
|
||||
@JoinColumn(name = "application_id")
|
||||
private Application application;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@MapsId("contactId")
|
||||
@JoinColumn(name = "contact_id")
|
||||
private Contact contact;
|
||||
|
||||
@Embeddable
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class ApplicationContactId implements Serializable {
|
||||
@Column(name = "application_id")
|
||||
private java.util.UUID applicationId;
|
||||
|
||||
@Column(name = "contact_id")
|
||||
private java.util.UUID contactId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.ldpv2.dto.request;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class AddContactToApplicationRequest {
|
||||
@NotNull(message = "Contact ID is required")
|
||||
private UUID contactId;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.ldpv2.dto.response;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ApplicationContactResponse {
|
||||
private UUID applicationId;
|
||||
private ContactResponse contact;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.ldpv2.repository;
|
||||
|
||||
import com.ldpv2.domain.entity.ApplicationContact;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Repository
|
||||
public interface ApplicationContactRepository extends JpaRepository<ApplicationContact, ApplicationContact.ApplicationContactId> {
|
||||
|
||||
@Query("SELECT ac FROM ApplicationContact ac " +
|
||||
"JOIN FETCH ac.contact c " +
|
||||
"JOIN FETCH c.contactRole " +
|
||||
"LEFT JOIN FETCH c.contactPersons cp " +
|
||||
"LEFT JOIN FETCH cp.person " +
|
||||
"WHERE ac.application.id = :applicationId")
|
||||
List<ApplicationContact> findByApplicationIdWithDetails(UUID applicationId);
|
||||
}
|
||||
@@ -1,23 +1,28 @@
|
||||
package com.ldpv2.service;
|
||||
|
||||
import com.ldpv2.domain.entity.Application;
|
||||
import com.ldpv2.domain.entity.ApplicationContact;
|
||||
import com.ldpv2.domain.entity.BusinessUnit;
|
||||
import com.ldpv2.domain.entity.Contact;
|
||||
import com.ldpv2.domain.enums.ApplicationStatus;
|
||||
import com.ldpv2.dto.request.CreateApplicationRequest;
|
||||
import com.ldpv2.dto.request.UpdateApplicationRequest;
|
||||
import com.ldpv2.dto.response.ApplicationResponse;
|
||||
import com.ldpv2.dto.response.BusinessUnitSummaryResponse;
|
||||
import com.ldpv2.dto.response.*;
|
||||
import com.ldpv2.exception.BadRequestException;
|
||||
import com.ldpv2.exception.ResourceNotFoundException;
|
||||
import com.ldpv2.repository.ApplicationContactRepository;
|
||||
import com.ldpv2.repository.ApplicationRepository;
|
||||
import com.ldpv2.repository.BusinessUnitRepository;
|
||||
import com.ldpv2.repository.ContactRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class ApplicationService {
|
||||
@@ -28,14 +33,18 @@ public class ApplicationService {
|
||||
@Autowired
|
||||
private BusinessUnitRepository businessUnitRepository;
|
||||
|
||||
@Autowired
|
||||
private ContactRepository contactRepository;
|
||||
|
||||
@Autowired
|
||||
private ApplicationContactRepository applicationContactRepository;
|
||||
|
||||
@Transactional
|
||||
public ApplicationResponse create(CreateApplicationRequest request) {
|
||||
// Validate business unit exists
|
||||
BusinessUnit businessUnit = businessUnitRepository.findById(request.getBusinessUnitId())
|
||||
.orElseThrow(() -> new ResourceNotFoundException(
|
||||
"Business unit not found with id: " + request.getBusinessUnitId()));
|
||||
|
||||
// Validate dates if both are provided
|
||||
if (request.getEndOfSupportDate() != null && request.getEndOfLifeDate() != null) {
|
||||
if (request.getEndOfSupportDate().isAfter(request.getEndOfLifeDate())) {
|
||||
throw new BadRequestException(
|
||||
@@ -88,7 +97,6 @@ public class ApplicationService {
|
||||
application.setEndOfSupportDate(request.getEndOfSupportDate());
|
||||
}
|
||||
|
||||
// Validate dates if both are set
|
||||
if (application.getEndOfSupportDate() != null && application.getEndOfLifeDate() != null) {
|
||||
if (application.getEndOfSupportDate().isAfter(application.getEndOfLifeDate())) {
|
||||
throw new BadRequestException(
|
||||
@@ -145,6 +153,52 @@ public class ApplicationService {
|
||||
applicationRepository.deleteById(id);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public ApplicationContactResponse addContact(UUID applicationId, UUID contactId) {
|
||||
Application application = applicationRepository.findById(applicationId)
|
||||
.orElseThrow(() -> new ResourceNotFoundException(
|
||||
"Application not found with id: " + applicationId));
|
||||
|
||||
Contact contact = contactRepository.findById(contactId)
|
||||
.orElseThrow(() -> new ResourceNotFoundException(
|
||||
"Contact not found with id: " + contactId));
|
||||
|
||||
application.addContact(contact);
|
||||
applicationRepository.save(application);
|
||||
|
||||
return new ApplicationContactResponse(applicationId, mapContactToResponse(contact));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void removeContact(UUID applicationId, UUID contactId) {
|
||||
Application application = applicationRepository.findById(applicationId)
|
||||
.orElseThrow(() -> new ResourceNotFoundException(
|
||||
"Application not found with id: " + applicationId));
|
||||
|
||||
Contact contact = contactRepository.findById(contactId)
|
||||
.orElseThrow(() -> new ResourceNotFoundException(
|
||||
"Contact not found with id: " + contactId));
|
||||
|
||||
application.removeContact(contact);
|
||||
applicationRepository.save(application);
|
||||
}
|
||||
|
||||
public List<ApplicationContactResponse> getApplicationContacts(UUID applicationId) {
|
||||
if (!applicationRepository.existsById(applicationId)) {
|
||||
throw new ResourceNotFoundException("Application not found with id: " + applicationId);
|
||||
}
|
||||
|
||||
List<ApplicationContact> appContacts = applicationContactRepository
|
||||
.findByApplicationIdWithDetails(applicationId);
|
||||
|
||||
return appContacts.stream()
|
||||
.map(ac -> new ApplicationContactResponse(
|
||||
applicationId,
|
||||
mapContactToResponse(ac.getContact())
|
||||
))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private ApplicationResponse mapToResponse(Application application) {
|
||||
BusinessUnitSummaryResponse buSummary = new BusinessUnitSummaryResponse(
|
||||
application.getBusinessUnit().getId(),
|
||||
@@ -163,4 +217,37 @@ public class ApplicationService {
|
||||
application.getUpdatedAt()
|
||||
);
|
||||
}
|
||||
|
||||
private ContactResponse mapContactToResponse(Contact contact) {
|
||||
ContactRoleResponse roleResponse = new ContactRoleResponse(
|
||||
contact.getContactRole().getId(),
|
||||
contact.getContactRole().getRoleName(),
|
||||
contact.getContactRole().getDescription(),
|
||||
contact.getContactRole().getCreatedAt(),
|
||||
contact.getContactRole().getUpdatedAt()
|
||||
);
|
||||
|
||||
List<PersonInContactResponse> personsResponse = contact.getContactPersons().stream()
|
||||
.map(cp -> {
|
||||
PersonResponse personResponse = new PersonResponse(
|
||||
cp.getPerson().getId(),
|
||||
cp.getPerson().getFirstName(),
|
||||
cp.getPerson().getLastName(),
|
||||
cp.getPerson().getEmail(),
|
||||
cp.getPerson().getPhone(),
|
||||
cp.getPerson().getCreatedAt(),
|
||||
cp.getPerson().getUpdatedAt()
|
||||
);
|
||||
return new PersonInContactResponse(personResponse, cp.isPrimary());
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return new ContactResponse(
|
||||
contact.getId(),
|
||||
roleResponse,
|
||||
personsResponse,
|
||||
contact.getCreatedAt(),
|
||||
contact.getUpdatedAt()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,5 +13,6 @@
|
||||
<include file="db/changelog/v1.0/005-create-contact-tables.xml"/>
|
||||
<include file="db/changelog/v1.0/006-create-version-table.xml"/>
|
||||
<include file="db/changelog/v1.0/007-create-deployment-table.xml"/>
|
||||
<include file="db/changelog/v1.0/008-create-application-contact-table.xml"/>
|
||||
|
||||
</databaseChangeLog>
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<databaseChangeLog
|
||||
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
|
||||
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
|
||||
|
||||
<changeSet id="008-create-application-contact-table" author="ldpv2-team">
|
||||
|
||||
<createTable tableName="application_contact">
|
||||
<column name="application_id" type="UUID">
|
||||
<constraints nullable="false"
|
||||
foreignKeyName="fk_application_contact_app"
|
||||
references="application(id)"
|
||||
deleteCascade="true"/>
|
||||
</column>
|
||||
<column name="contact_id" type="UUID">
|
||||
<constraints nullable="false"
|
||||
foreignKeyName="fk_application_contact_contact"
|
||||
references="contact(id)"
|
||||
deleteCascade="true"/>
|
||||
</column>
|
||||
</createTable>
|
||||
|
||||
<addPrimaryKey tableName="application_contact"
|
||||
columnNames="application_id, contact_id"
|
||||
constraintName="pk_application_contact"/>
|
||||
|
||||
<createIndex tableName="application_contact" indexName="idx_app_contact_application">
|
||||
<column name="application_id"/>
|
||||
</createIndex>
|
||||
|
||||
<createIndex tableName="application_contact" indexName="idx_app_contact_contact">
|
||||
<column name="contact_id"/>
|
||||
</createIndex>
|
||||
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
Reference in New Issue
Block a user