/* * Copyright (c) 2005-2011 Grameen Foundation USA * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. * * See also http://www.apache.org/licenses/LICENSE-2.0.html for an * explanation of the license and how it is applied. */ package org.mifos.accounts.loan.business; import java.io.Serializable; import java.sql.Date; import java.util.Collection; import java.util.HashSet; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.Transient; import org.hibernate.annotations.Columns; import org.hibernate.annotations.Type; import org.joda.time.LocalDate; import org.mifos.accounts.business.AccountBO; import org.mifos.accounts.business.AccountFeesActionDetailEntity; import org.mifos.accounts.loan.util.helpers.RepaymentScheduleInstallment; import org.mifos.accounts.util.helpers.PaymentStatus; import org.mifos.application.master.business.MifosCurrency; import org.mifos.customers.business.CustomerBO; import org.mifos.framework.util.helpers.DateUtils; import org.mifos.framework.util.helpers.Money; @NamedQueries( { @NamedQuery( name = "originalLoanScheduleEntity.getScheduleForLoan", query = " from org.mifos.accounts.loan.business.OriginalLoanScheduleEntity originalLoanSchedule" + " where originalLoanSchedule.account.id = :id" ) }) @Entity @Table(name = "original_loan_schedule") public class OriginalLoanScheduleEntity implements Comparable<OriginalLoanScheduleEntity>, Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") private Integer actionDateId; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "account_id") private AccountBO account; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "customer_id") private CustomerBO customer; @Column(name = "installment_id") private Short installmentId; @Column(name = "action_date") private Date actionDate; @Column(name = "payment_status") private Short paymentStatus; @Column(name = "payment_date") private Date paymentDate; @Type(type = "org.mifos.framework.util.helpers.MoneyCompositeUserType") @Columns(columns = { @Column(name = "principal_currency_id"), @Column(name = "principal") }) private Money principal; @Type(type = "org.mifos.framework.util.helpers.MoneyCompositeUserType") @Columns(columns = { @Column(name = "interest_currency_id"), @Column(name = "interest") }) private Money interest; // TODO: Instance variable "penalty" appears to be unused. Verify and // remove. @Type(type = "org.mifos.framework.util.helpers.MoneyCompositeUserType") @Columns(columns = { @Column(name = "penalty_currency_id"), @Column(name = "penalty") }) private Money penalty; @Transient private Money extraInterest; @Type(type = "org.mifos.framework.util.helpers.MoneyCompositeUserType") @Columns(columns = { @Column(name = "miscFees_currency_id"), @Column(name = "miscFees") }) private Money miscFee; @Type(type = "org.mifos.framework.util.helpers.MoneyCompositeUserType") @Columns(columns = { @Column(name = "misc_penalty_currency_id"), @Column(name = "misc_penalty") }) private Money miscPenalty; @Type(type = "org.mifos.framework.util.helpers.MoneyCompositeUserType") @Columns(columns = { @Column(name = "principal_paid_currency_id"), @Column(name = "principal_paid") }) private Money principalPaid; @Type(type = "org.mifos.framework.util.helpers.MoneyCompositeUserType") @Columns(columns = { @Column(name = "interest_paid_currency_id"), @Column(name = "interest_paid") }) private Money interestPaid; @Type(type = "org.mifos.framework.util.helpers.MoneyCompositeUserType") @Columns(columns = { @Column(name = "penalty_paid_currency_id"), @Column(name = "penalty_paid") }) private Money penaltyPaid; @Transient private Money extraInterestPaid; @Type(type = "org.mifos.framework.util.helpers.MoneyCompositeUserType") @Columns(columns = { @Column(name = "misc_fees_paid_currency_id"), @Column(name = "misc_fees_paid") }) private Money miscFeePaid; @Type(type = "org.mifos.framework.util.helpers.MoneyCompositeUserType") @Columns(columns = { @Column(name = "misc_penalty_paid_currency_id"), @Column(name = "misc_penalty_paid") }) private Money miscPenaltyPaid; @OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY) @JoinColumn(name = "id", updatable = true, insertable = true) private Set<OriginalLoanFeeScheduleEntity> accountFeesActionDetails = new HashSet<OriginalLoanFeeScheduleEntity>(); @Column(name = "version_no") private int versionNo; @Transient private PaymentAllocation paymentAllocation; public OriginalLoanScheduleEntity() { } public OriginalLoanScheduleEntity(LoanScheduleEntity loanScheduleEntity) { this.actionDateId = null; this.account = loanScheduleEntity.getAccount(); this.customer = loanScheduleEntity.getCustomer(); this.installmentId = loanScheduleEntity.getInstallmentId(); this.actionDate = loanScheduleEntity.getActionDate(); Short paymentStatus = loanScheduleEntity.getPaymentStatus(); if (paymentStatus != null) { this.paymentStatus = paymentStatus; } this.principal = loanScheduleEntity.getPrincipal(); this.interest = loanScheduleEntity.getInterest(); this.penalty = loanScheduleEntity.getPenalty(); this.extraInterest = loanScheduleEntity.getExtraInterest(); this.miscFee = loanScheduleEntity.getMiscFee(); this.miscPenalty = loanScheduleEntity.getMiscPenalty(); this.miscFeePaid = loanScheduleEntity.getMiscFeePaid(); this.miscPenaltyPaid = loanScheduleEntity.getMiscPenaltyPaid(); this.extraInterestPaid = loanScheduleEntity.getExtraInterestPaid(); this.penaltyPaid = loanScheduleEntity.getPenaltyPaid(); this.interestPaid = loanScheduleEntity.getInterestPaid(); this.principalPaid = loanScheduleEntity.getPrincipalPaid(); this.versionNo = loanScheduleEntity.getVersionNo(); this.paymentAllocation = loanScheduleEntity.getPaymentAllocation(); for (AccountFeesActionDetailEntity accountFeesActionDetail : loanScheduleEntity.getAccountFeesActionDetails()) { this.addAccountFeesAction(new OriginalLoanFeeScheduleEntity(accountFeesActionDetail, this)); } reset(getCurrency()); } private void reset(MifosCurrency currency) { this.penaltyPaid = new Money(currency); this.extraInterest = new Money(currency); this.miscFeePaid = new Money(currency); this.miscPenaltyPaid = new Money(currency); this.principalPaid = new Money(currency); this.interestPaid = new Money(currency); this.penaltyPaid = new Money(currency); this.extraInterestPaid = new Money(currency); this.miscFeePaid = new Money(currency); this.miscPenaltyPaid = new Money(currency); } public Money getInterest() { return interest; } public void setInterest(Money interest) { this.interest = interest; } public Money getInterestPaid() { return interestPaid; } void setInterestPaid(Money interestPaid) { this.interestPaid = interestPaid; } void setPenalty(Money penalty) { this.penalty = penalty; } public Money getPenaltyPaid() { return penaltyPaid; } void setPenaltyPaid(Money penaltyPaid) { this.penaltyPaid = penaltyPaid; } public Money getPrincipal() { return principal; } public void setPrincipal(Money principal) { this.principal = principal; } public Money getPrincipalPaid() { return principalPaid; } void setPrincipalPaid(Money principalPaid) { this.principalPaid = principalPaid; } public Money getPrincipalDue() { return principal.subtract(principalPaid); } public Money getInterestDue() { return interest.subtract(interestPaid); } public Money getPenalty() { return penalty; } public Collection<OriginalLoanFeeScheduleEntity> getAccountFeesActionDetails() { return accountFeesActionDetails; } public void addAccountFeesAction(OriginalLoanFeeScheduleEntity accountFeesAction) { accountFeesActionDetails.add(accountFeesAction); } public Money getMiscFee() { return miscFee; } void setMiscFee(Money miscFee) { this.miscFee = miscFee; } public Money getMiscFeePaid() { return miscFeePaid; } void setMiscFeePaid(Money miscFeePaid) { this.miscFeePaid = miscFeePaid; } public Money getMiscPenalty() { return miscPenalty; } void setMiscPenalty(Money miscPenalty) { this.miscPenalty = miscPenalty; } public Money getMiscPenaltyPaid() { return miscPenaltyPaid; } public Money getMiscPenaltyDue() { return miscPenalty.subtract(miscPenaltyPaid); } void setMiscPenaltyPaid(Money miscPenaltyPaid) { this.miscPenaltyPaid = miscPenaltyPaid; } public Money getPenaltyDue() { return (penalty.add(miscPenalty)).subtract(penaltyPaid.add(miscPenaltyPaid)); } public Money getTotalDue() { return principal.subtract(principalPaid).add(getEffectiveInterestDue()).add(getPenaltyDue()).add(getMiscFeeDue()); } public Money getTotalDueWithFees() { return getTotalDue().add(getTotalFeesDue()); } void removeAccountFeesActionDetailEntity(AccountFeesActionDetailEntity accountFeesActionDetailEntity) { accountFeesActionDetails.remove(accountFeesActionDetailEntity); } public Money getMiscFeeDue() { return getMiscFee().subtract(getMiscFeePaid()); } public Money getTotalFeesDue() { Money totalFees = new Money(getCurrency()); for (OriginalLoanFeeScheduleEntity obj : accountFeesActionDetails) { totalFees = totalFees.add(obj.getFeeDue()); } return totalFees; } public Money getTotalScheduledFeeAmountWithMiscFee() { Money totalFees = new Money(getCurrency()); for (OriginalLoanFeeScheduleEntity obj : accountFeesActionDetails) { totalFees = totalFees.add(obj.getFeeAmount()); } totalFees = totalFees.add(getMiscFee()); return totalFees; } public Money getTotalPaymentDue() { return getTotalDue().add(getTotalFeesDue()); } public void setVersionNo(int versionNo) { this.versionNo = versionNo; } public int getVersionNo() { return versionNo; } public RepaymentScheduleInstallment toDto() { return new RepaymentScheduleInstallment(this.installmentId, this.actionDate, this.principal, this.interest, this.getTotalFeesDue(), this.miscFee, this.miscPenalty); } public Money getExtraInterest() { return extraInterest == null ? Money.zero(getCurrency()) : extraInterest; } public void setExtraInterest(Money extraInterest) { this.extraInterest = extraInterest; } public Money getExtraInterestPaid() { return extraInterestPaid == null ? Money.zero(getCurrency()) : extraInterestPaid; } public void setExtraInterestPaid(Money extraInterestPaid) { this.extraInterestPaid = extraInterestPaid; } public Money getExtraInterestDue() { return getExtraInterest().subtract(getExtraInterestPaid()); } public Money getEffectiveInterestDue() { return getInterestDue().add(getExtraInterestDue()); } private void initPaymentAllocation(MifosCurrency currency) { paymentAllocation = new PaymentAllocation(currency); } public PaymentAllocation getPaymentAllocation() { return paymentAllocation; } public Integer getActionDateId() { return actionDateId; } public void setActionDateId(Integer actionDateId) { this.actionDateId = actionDateId; } public AccountBO getAccount() { return account; } public CustomerBO getCustomer() { return customer; } public Short getInstallmentId() { return installmentId; } public Date getActionDate() { return actionDate; } public void setActionDate(Date actionDate) { this.actionDate = actionDate; } public Date getPaymentDate() { return paymentDate; } public void setPaymentDate(Date paymentDate) { this.paymentDate = paymentDate; } public Short getPaymentStatus() { return paymentStatus; } public PaymentStatus getPaymentStatusAsEnum() { return PaymentStatus.fromInt(paymentStatus); } public void setPaymentStatus(PaymentStatus status) { this.paymentStatus = status.getValue(); } public void setPaymentStatus(Short paymentStatus) { this.paymentStatus = paymentStatus; } public int compareDate(java.util.Date date) { return this.getActionDate().compareTo(date); } public boolean isPaid() { return this.getPaymentStatusAsEnum() == PaymentStatus.PAID; } @Override public int compareTo(OriginalLoanScheduleEntity obj) { return this.getInstallmentId().compareTo(obj.getInstallmentId()); } public MifosCurrency getCurrency() { return account.getCurrency(); } public boolean isDueToday() { return DateUtils.getDateWithoutTimeStamp(this.getActionDate().getTime()).equals( DateUtils.getCurrentDateWithoutTimeStamp()); } public void setAccount(AccountBO account) { this.account = account; } public boolean isBeforeOrOn(LocalDate date) { return new LocalDate(this.actionDate).isBefore(date) || new LocalDate(this.actionDate).isEqual(date); } public boolean isNotPaid() { return !this.isPaid(); } public void setInstallmentId(Short installmentId) { this.installmentId = installmentId; } }