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
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
import com.devoops.accommodation.entity.Accommodation;
import com.devoops.accommodation.entity.AvailabilityPeriod;
import com.devoops.accommodation.entity.PricingMode;
import com.devoops.accommodation.grpc.proto.AccommodationInternalServiceGrpc;
import com.devoops.accommodation.grpc.proto.ReservationValidationRequest;
import com.devoops.accommodation.grpc.proto.ReservationValidationResponse;
import com.devoops.accommodation.grpc.proto.*;
import com.devoops.accommodation.repository.AccommodationRepository;
import com.devoops.accommodation.repository.AvailabilityPeriodRepository;
import com.devoops.accommodation.service.AccommodationService;
import io.grpc.stub.StreamObserver;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -27,6 +26,7 @@ public class AccommodationGrpcService extends AccommodationInternalServiceGrpc.A

private final AccommodationRepository accommodationRepository;
private final AvailabilityPeriodRepository availabilityPeriodRepository;
private final AccommodationService accommodationService;

@Override
public void validateAndCalculatePrice(
Expand Down Expand Up @@ -126,4 +126,43 @@ private ReservationValidationResponse buildErrorResponse(String errorCode, Strin
.setErrorMessage(errorMessage)
.build();
}

@Override
public void deleteAccommodationsByHost(DeleteByHostRequest request,
StreamObserver<DeleteByHostResponse> responseObserver) {
log.debug("gRPC: Deleting all accommodations for host: {}", request.getHostId());

try {
UUID hostId = UUID.fromString(request.getHostId());
int deletedCount = accommodationService.deleteAllByHostId(hostId);

log.info("Deleted {} accommodations for host {}", deletedCount, hostId);

DeleteByHostResponse response = DeleteByHostResponse.newBuilder()
.setSuccess(true)
.setDeletedCount(deletedCount)
.build();

responseObserver.onNext(response);
responseObserver.onCompleted();
} catch (IllegalArgumentException e) {
log.error("Invalid host ID format: {}", request.getHostId(), e);
DeleteByHostResponse response = DeleteByHostResponse.newBuilder()
.setSuccess(false)
.setDeletedCount(0)
.setErrorMessage("Invalid host ID format")
.build();
responseObserver.onNext(response);
responseObserver.onCompleted();
} catch (Exception e) {
log.error("Failed to delete accommodations for host {}", request.getHostId(), e);
DeleteByHostResponse response = DeleteByHostResponse.newBuilder()
.setSuccess(false)
.setDeletedCount(0)
.setErrorMessage("Failed to delete accommodations: " + e.getMessage())
.build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

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

Expand All @@ -24,4 +26,19 @@ WHERE LOWER(a.address) LIKE LOWER(CONCAT('%', :location, '%'))
List<Accommodation> searchByLocationAndGuests(
@Param("location") String location,
@Param("guests") int guests);

/**
* Soft delete all accommodations for a host.
* Used when host deletes their account.
*
* @return the number of accommodations soft-deleted
*/
@Modifying
@Query("""
UPDATE Accommodation a
SET a.isDeleted = true, a.updatedAt = :now
WHERE a.hostId = :hostId
AND a.isDeleted = false
""")
int softDeleteByHostId(@Param("hostId") UUID hostId, @Param("now") LocalDateTime now);
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -115,6 +116,18 @@ public void delete(UUID id, UserContext userContext) {
accommodationRepository.save(accommodation);
}

/**
* Soft delete all accommodations owned by a host.
* Used when a host deletes their account (cascade deletion).
*
* @param hostId the ID of the host whose accommodations should be deleted
* @return the number of accommodations soft-deleted
*/
@Transactional
public int deleteAllByHostId(UUID hostId) {
return accommodationRepository.softDeleteByHostId(hostId, LocalDateTime.now());
}

@Transactional(readOnly = true)
public Page<AccommodationSearchResponse> search(String location, int guests, LocalDate startDate, LocalDate endDate, int page, int size) {
if (!endDate.isAfter(startDate)) {
Expand Down
11 changes: 11 additions & 0 deletions src/main/proto/accommodation_internal.proto
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ option java_package = "com.devoops.accommodation.grpc.proto";

service AccommodationInternalService {
rpc ValidateAndCalculatePrice(ReservationValidationRequest) returns (ReservationValidationResponse);
rpc DeleteAccommodationsByHost(DeleteByHostRequest) returns (DeleteByHostResponse);
}

message ReservationValidationRequest {
Expand All @@ -25,3 +26,13 @@ message ReservationValidationResponse {
string approval_mode = 7;
string accommodation_name = 8;
}

message DeleteByHostRequest {
string host_id = 1;
}

message DeleteByHostResponse {
bool success = 1;
int32 deleted_count = 2;
string error_message = 3;
}