package org.kuali.kfs.module.ar.businessobject;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.kuali.kfs.coa.businessobject.AccountingPeriod;
import org.kuali.kfs.coa.service.AccountingPeriodService;
import org.kuali.kfs.module.ar.ArConstants;
import java.sql.Date;
public abstract class BillingPeriod {
protected Date startDate;
protected Date endDate;
protected boolean billable;
protected final AccountingPeriodService accountingPeriodService;
protected final String billingFrequency;
protected final Date awardStartDate;
protected final Date currentDate;
protected final Date lastBilledDate;
protected BillingPeriod(String billingFrequency, Date awardStartDate, Date currentDate, Date lastBilledDate, AccountingPeriodService accountingPeriodService) {
this.awardStartDate = awardStartDate;
this.lastBilledDate = lastBilledDate;
this.accountingPeriodService = accountingPeriodService;
this.billingFrequency = billingFrequency;
this.currentDate = currentDate;
}
public Date getStartDate() {
return startDate;
}
public Date getEndDate() {
return endDate;
}
public static BillingPeriod determineBillingPeriodPriorTo(Date awardStartDate, Date currentDate, Date lastBilledDate, String billingFrequency, AccountingPeriodService accountingPeriodService) {
BillingPeriod billingPeriod;
if (StringUtils.equals(billingFrequency, ArConstants.LOC_BILLING_SCHEDULE_CODE)) {
billingPeriod = new LetterOfCreditBillingPeriod(billingFrequency, awardStartDate, currentDate, lastBilledDate, accountingPeriodService);
} else {
billingPeriod = new TimeBasedBillingPeriod(billingFrequency, awardStartDate, currentDate, lastBilledDate, accountingPeriodService);
}
billingPeriod.billable = billingPeriod.canThisBeBilled();
if (billingPeriod.billable) {
billingPeriod.startDate = billingPeriod.determineStartDate();
billingPeriod.endDate = billingPeriod.determineEndDateByFrequency();
}
return billingPeriod;
}
protected abstract Date determineEndDateByFrequency();
protected AccountingPeriod findAccountingPeriodBy(Date date) {
return accountingPeriodService.getByDate(date);
}
protected boolean canThisBeBilled() {
if (awardStartDate.after(currentDate)) {
return false; // do not bill future awards!
}
if (lastBilledDate == null) {
return true;
}
return canThisBeBilledByBillingFrequency();
}
protected abstract boolean canThisBeBilledByBillingFrequency();
protected Date determineStartDate() {
if (lastBilledDate == null) {
return awardStartDate;
}
return determineStartDateByFrequency();
}
protected abstract Date determineStartDateByFrequency();
protected Date calculatePreviousDate(Date date) {
return new Date(DateUtils.addDays(date, -1).getTime());
}
protected Date calculateNextDay(Date date) {
return new Date(DateUtils.addDays(date, 1).getTime());
}
public boolean isBillable() {
return billable;
}
}