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.
 
 
 

58 lines
3.1 KiB

package com.mydreamjob.application;
import com.mydreamjob.audit.AuditContext;
import com.mydreamjob.audit.AuditService;
import com.mydreamjob.common.exception.BusinessException;
import com.mydreamjob.common.exception.ErrorCode;
import com.mydreamjob.company.Company;
import com.mydreamjob.company.CompanyRepository;
import com.mydreamjob.company.VerifiedCompanyGuard;
import com.mydreamjob.job.Job;
import com.mydreamjob.job.JobService;
import com.mydreamjob.notification.NotificationService;
import com.mydreamjob.security.UserRoleGuard;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.Clock;
import java.time.LocalDateTime;
import java.util.Set;
@Service
@RequiredArgsConstructor
public class ApplicationAcceptanceService {
private final UserRoleGuard roles;
private final CompanyRepository companies;
private final ApplicationRepository applications;
private final JobService jobs;
private final ApplicationStatusHistoryRepository history;
private final AuditService audit;
private final NotificationService notifications;
private final Clock clock;
/** 与撤回/状态推进使用相同投递行锁;重试只产生一次接受记录和通知。 */
@Transactional
public Application accept(Long actorUserId, Long applicationId, AuditContext context) {
roles.requireCompany(actorUserId);
Company company = VerifiedCompanyGuard.requireVerified(companies.findByOwnerUserId(actorUserId).orElse(null));
Application app = applications.findLockedById(applicationId)
.orElseThrow(() -> new BusinessException(ErrorCode.APPLICATION_NOT_FOUND));
Job job = jobs.getJob(app.getJobId());
if (!company.getId().equals(job.getCompanyId()))
throw new BusinessException(ErrorCode.APPLICATION_OWNER_MISMATCH);
if (!Set.of("SUBMITTED","VIEWED","INTERVIEW","HIRED").contains(app.getStatus()))
throw new BusinessException(ErrorCode.INVALID_APPLICATION_STATUS_TRANSITION);
// 已录用仍可补记明确接受;已经接受时不覆盖原始时间/审计。
if (app.getCompanyAcceptedAt() != null) return app;
app.setCompanyAcceptedAt(LocalDateTime.now(clock).truncatedTo(java.time.temporal.ChronoUnit.MICROS));
app = applications.save(app);
history.save(ApplicationStatusHistory.builder().applicationId(app.getId())
.operatorUserId(actorUserId).fromStatus(app.getStatus()).toStatus(app.getStatus())
.reason("COMPANY_ACCEPTED: company accepted application; communication unlocked").build());
audit.log(actorUserId,"ACCEPT_APPLICATION","APPLICATION",app.getId(),
"Company accepted application; communication unlocked",context);
notifications.publishEvent(app.getStudentUserId(),"APPLICATION_ACCEPTED","企业已接受投递",
"企业已接受你的投递,可以开始沟通","APPLICATION",app.getId(),"accept-application-"+app.getId());
return app;
}
}