package ca.intelliware.ihtsdo.mlds.service;
import javax.annotation.Resource;
import javax.transaction.Transactional;
import org.joda.time.Instant;
import org.springframework.stereotype.Service;
import ca.intelliware.ihtsdo.mlds.domain.UsageReportState;
import ca.intelliware.ihtsdo.mlds.domain.CommercialUsage;
import ca.intelliware.ihtsdo.mlds.repository.CommercialUsageRepository;
@Service
@Transactional
public class CommercialUsageService {
@Resource CommercialUsageRepository commercialUsageRepository;
@Resource CommercialUsageResetter commercialUsageResetter;
@Resource CommercialUsageAuthorizationChecker authorizationChecker;
@Resource CommercialUsageAuditEvents commercialUsageAuditEvents;
public CommercialUsage transitionCommercialUsageApproval(CommercialUsage commercialUsage, UsageReportTransition transition) {
// FIXME Extract out to "workflow" handler
if (UsageReportState.NOT_SUBMITTED.equals(commercialUsage.getState()) && UsageReportTransition.SUBMIT.equals(transition)
&& commercialUsage.isActive()) {
commercialUsage = submitUsage(commercialUsage);
} else if (UsageReportState.CHANGE_REQUESTED.equals(commercialUsage.getState()) && UsageReportTransition.SUBMIT.equals(transition)
&& commercialUsage.isActive()) {
commercialUsage = resubmitUsage(commercialUsage);
} else if ((UsageReportState.SUBMITTED.equals(commercialUsage.getState())
|| UsageReportState.RESUBMITTED.equals(commercialUsage.getState())
|| UsageReportState.PENDING_INVOICE .equals(commercialUsage.getState())
|| UsageReportState.INVOICE_SENT.equals(commercialUsage.getState())
|| UsageReportState.PAID.equals(commercialUsage.getState())
)
&& UsageReportTransition.RETRACT.equals(transition) && commercialUsage.isActive()) {
commercialUsage = retractUsage(commercialUsage);
} else if ((UsageReportState.SUBMITTED.equals(commercialUsage.getState()) || UsageReportState.RESUBMITTED.equals(commercialUsage
.getState())) && UsageReportTransition.PENDING_INVOICE.equals(transition) && commercialUsage.isActive()) {
commercialUsage = setState(commercialUsage, UsageReportState.PENDING_INVOICE);
} else if (UsageReportState.PENDING_INVOICE.equals(commercialUsage.getState())
&& UsageReportTransition.INVOICE_SENT.equals(transition)
&& commercialUsage.isActive()) {
commercialUsage = setState(commercialUsage, UsageReportState.INVOICE_SENT);
} else if (UsageReportState.INVOICE_SENT.equals(commercialUsage.getState())
&& UsageReportTransition.PAID.equals(transition)
&& commercialUsage.isActive()) {
commercialUsage = setState(commercialUsage, UsageReportState.PAID);
} else {
throw new IllegalStateException("Unsupported usage report transition of" + transition.name() + " while in state " + commercialUsage.getState().name());
}
commercialUsageAuditEvents.logUsageReportStateChange(commercialUsage);
return commercialUsage;
}
private CommercialUsage setState(CommercialUsage commercialUsage, UsageReportState newState) {
authorizationChecker.checkCanReviewUsageReports();
commercialUsage.setState(newState);
commercialUsage = commercialUsageRepository.save(commercialUsage);
return commercialUsage;
}
private CommercialUsage retractUsage(CommercialUsage commercialUsage) {
// Mark original usage as no-longer effective
commercialUsage.setEffectiveTo(Instant.now());
commercialUsage = commercialUsageRepository.saveAndFlush(commercialUsage);
// Create duplicate usage to replace original and become the active one
commercialUsageResetter.detachAndReset(commercialUsage, commercialUsage.getStartDate(), commercialUsage.getEndDate());
commercialUsage.setState(UsageReportState.CHANGE_REQUESTED);
commercialUsage = commercialUsageRepository.save(commercialUsage);
return commercialUsage;
}
private CommercialUsage submitUsage(CommercialUsage commercialUsage) {
commercialUsage.setState(UsageReportState.SUBMITTED);
commercialUsage.setSubmitted(Instant.now());
commercialUsage = commercialUsageRepository.save(commercialUsage);
return commercialUsage;
}
private CommercialUsage resubmitUsage(CommercialUsage commercialUsage) {
commercialUsage.setState(UsageReportState.RESUBMITTED);
commercialUsage.setSubmitted(Instant.now());
commercialUsage = commercialUsageRepository.save(commercialUsage);
return commercialUsage;
}
}