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
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;
|
|
}
|
|
}
|
|
|