feat(ops): add service activation request review endpoints

OpsController: GET /api/ops/service-requests (with optional status filter),
POST /api/ops/service-requests/{id}/approve, POST .../reject.
OpsService: listServiceRequests() delegates to existing repository queries.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
这个提交包含在:
XuqmGroup 2026-04-25 06:40:27 +08:00
父节点 ef9b43417e
当前提交 b13820032d
共有 2 个文件被更改,包括 56 次插入4 次删除

查看文件

@ -1,9 +1,10 @@
package com.xuqm.tenant.controller;
import com.xuqm.common.model.ApiResponse;
import com.xuqm.tenant.entity.ServiceActivationRequestEntity;
import com.xuqm.tenant.entity.TenantEntity;
import com.xuqm.tenant.service.FeatureServiceManager;
import com.xuqm.tenant.service.OpsService;
import jakarta.validation.constraints.NotBlank;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
@ -22,9 +23,11 @@ import java.util.Map;
public class OpsController {
private final OpsService opsService;
private final FeatureServiceManager featureServiceManager;
public OpsController(OpsService opsService) {
public OpsController(OpsService opsService, FeatureServiceManager featureServiceManager) {
this.opsService = opsService;
this.featureServiceManager = featureServiceManager;
}
@PostMapping("/api/auth/ops/login")
@ -59,4 +62,38 @@ public class OpsController {
public ResponseEntity<ApiResponse<Map<String, Object>>> statistics() {
return ResponseEntity.ok(ApiResponse.success(opsService.statistics()));
}
@GetMapping("/api/ops/service-requests")
@PreAuthorize("hasAuthority('ROLE_OPS')")
public ResponseEntity<ApiResponse<Map<String, Object>>> listServiceRequests(
@RequestParam(required = false) String status,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size) {
Page<ServiceActivationRequestEntity> result = opsService.listServiceRequests(status, page, size);
return ResponseEntity.ok(ApiResponse.success(Map.of(
"content", result.getContent(),
"total", result.getTotalElements(),
"totalPages", result.getTotalPages()
)));
}
@PostMapping("/api/ops/service-requests/{requestId}/approve")
@PreAuthorize("hasAuthority('ROLE_OPS')")
public ResponseEntity<ApiResponse<ServiceActivationRequestEntity>> approveRequest(
@PathVariable String requestId,
@RequestBody(required = false) Map<String, String> body) {
String reviewNote = body != null ? body.getOrDefault("reviewNote", "") : "";
return ResponseEntity.ok(ApiResponse.success(
featureServiceManager.approveRequest(requestId, reviewNote)));
}
@PostMapping("/api/ops/service-requests/{requestId}/reject")
@PreAuthorize("hasAuthority('ROLE_OPS')")
public ResponseEntity<ApiResponse<ServiceActivationRequestEntity>> rejectRequest(
@PathVariable String requestId,
@RequestBody(required = false) Map<String, String> body) {
String reviewNote = body != null ? body.getOrDefault("reviewNote", "") : "";
return ResponseEntity.ok(ApiResponse.success(
featureServiceManager.rejectRequest(requestId, reviewNote)));
}
}

查看文件

@ -2,9 +2,11 @@ package com.xuqm.tenant.service;
import com.xuqm.common.security.JwtUtil;
import com.xuqm.tenant.entity.OpsAdminEntity;
import com.xuqm.tenant.entity.ServiceActivationRequestEntity;
import com.xuqm.tenant.entity.TenantEntity;
import com.xuqm.tenant.repository.AppRepository;
import com.xuqm.tenant.repository.OpsAdminRepository;
import com.xuqm.tenant.repository.ServiceActivationRequestRepository;
import com.xuqm.tenant.repository.TenantRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
@ -23,15 +25,18 @@ public class OpsService {
private final TenantRepository tenantRepository;
private final AppRepository appRepository;
private final OpsAdminRepository opsAdminRepository;
private final ServiceActivationRequestRepository requestRepository;
private final PasswordEncoder passwordEncoder;
private final JwtUtil jwtUtil;
public OpsService(TenantRepository tenantRepository, AppRepository appRepository,
OpsAdminRepository opsAdminRepository, PasswordEncoder passwordEncoder,
JwtUtil jwtUtil) {
OpsAdminRepository opsAdminRepository,
ServiceActivationRequestRepository requestRepository,
PasswordEncoder passwordEncoder, JwtUtil jwtUtil) {
this.tenantRepository = tenantRepository;
this.appRepository = appRepository;
this.opsAdminRepository = opsAdminRepository;
this.requestRepository = requestRepository;
this.passwordEncoder = passwordEncoder;
this.jwtUtil = jwtUtil;
}
@ -77,6 +82,16 @@ public class OpsService {
);
}
public Page<ServiceActivationRequestEntity> listServiceRequests(String statusStr, int page, int size) {
var pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt"));
if (statusStr != null && !statusStr.isEmpty()) {
ServiceActivationRequestEntity.Status status =
ServiceActivationRequestEntity.Status.valueOf(statusStr.toUpperCase());
return requestRepository.findByStatusOrderByCreatedAtDesc(status, pageable);
}
return requestRepository.findAllByOrderByCreatedAtDesc(pageable);
}
public void initDefaultAdmin(String username, String rawPassword) {
if (opsAdminRepository.findByUsername(username).isPresent()) return;
OpsAdminEntity admin = new OpsAdminEntity();