轻松聘AI开发
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

91 lines
4.3 KiB

package com.mydreamjob.salarycalculator;
import com.mydreamjob.common.api.ApiResponse;
import com.mydreamjob.common.api.PageResponse;
import com.mydreamjob.common.exception.BusinessException;
import com.mydreamjob.common.exception.ErrorCode;
import com.mydreamjob.salarycalculator.dto.SalaryCalculationRequest;
import com.mydreamjob.salarycalculator.dto.SalaryCalculationResponse;
import com.mydreamjob.salarycalculator.dto.SalaryHistoryDetailResponse;
import com.mydreamjob.salarycalculator.dto.SalaryHistorySummaryResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@Tag(name = "薪资计算器", description = "城市政策、到手工资估算与历史记录")
@RestController
@RequestMapping("/salary-calculator")
@RequiredArgsConstructor
public class SalaryCalculationController {
private final SalaryCalculationService calculationService;
private final SalaryHistoryService historyService;
@Operation(summary = "计算并保存到手工资", description = "仅 STUDENT;未发布政策返回 404/10601,幂等重放不可绕过发布门禁;本人历史查询不受影响")
@PostMapping("/calculations")
public ResponseEntity<ApiResponse<SalaryCalculationResponse>> calculate(
@Valid @RequestBody SalaryCalculationRequest body, HttpServletRequest request) {
Long userId = resolveUserId();
return ResponseEntity.ok(ApiResponse.ok(
calculationService.calculateAndSave(userId, body), getRequestId(request)));
}
@Operation(summary = "查询本人薪资历史", description = "仅 STUDENT;按创建时间倒序分页")
@GetMapping("/calculations")
public ResponseEntity<ApiResponse<PageResponse<SalaryHistorySummaryResponse>>> list(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size,
HttpServletRequest request) {
Long userId = resolveUserId();
return ResponseEntity.ok(ApiResponse.ok(
historyService.list(userId, page, size), getRequestId(request)));
}
@Operation(summary = "查询本人薪资历史详情", description = "仅 STUDENT;返回完整快照")
@GetMapping("/calculations/{id}")
public ResponseEntity<ApiResponse<SalaryHistoryDetailResponse>> get(
@PathVariable Long id, HttpServletRequest request) {
Long userId = resolveUserId();
return ResponseEntity.ok(ApiResponse.ok(
historyService.get(userId, id), getRequestId(request)));
}
@Operation(summary = "删除本人薪资历史", description = "仅 STUDENT;物理删除")
@DeleteMapping("/calculations/{id}")
public ResponseEntity<ApiResponse<Void>> delete(
@PathVariable Long id, HttpServletRequest request) {
Long userId = resolveUserId();
historyService.delete(userId, id);
return ResponseEntity.ok(ApiResponse.ok(null, getRequestId(request)));
}
private Long resolveUserId() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth == null || !auth.isAuthenticated()
|| "anonymousUser".equals(String.valueOf(auth.getPrincipal()))) {
throw new BusinessException(ErrorCode.UNAUTHORIZED);
}
try {
return Long.valueOf(auth.getName());
} catch (NumberFormatException ex) {
throw new BusinessException(ErrorCode.UNAUTHORIZED);
}
}
private String getRequestId(HttpServletRequest request) {
return request.getHeader("X-Request-Id");
}
}