/**
* This file is part of Pau's Asset Manager Project.
*
* Pau's Asset Manager Project is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Pau's Asset Manager Project is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Pau's Asset Manager Project. If not, see <http://www.gnu.org/licenses/>.
*/
package org.pau.assetmanager.entities;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Transient;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.pau.assetmanager.business.TimeDependentConstantsBusiness;
import org.pau.assetmanager.utils.AssetManagerRuntimeException;
import org.pau.assetmanager.viewmodel.type.PropertyType;
import org.pau.assetmanager.viewmodel.type.TimeDependentConstantType;
import org.zkoss.bind.annotation.NotifyChange;
/**
* This class represents a book income annotation for a property book
*
* @author Pau Carré Cardona
*
*/
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public class PropertyIncomeAnnotation extends IncomeAnnotation implements EntityInterface {
private static final long serialVersionUID = 1L;
private static final Logger logger = LogManager.getLogger(PropertyIncomeAnnotation.class);
public static final Boolean DEFAULT_FOR_COMPANY = false;
public PropertyIncomeAnnotation() {
super();
}
/**
* This class represents the default values retrieved by the database
* It is not possible to include that part of the code directly in the constructor
* as it will generate a 'recursive dependency' in the initialization of JPA which
* will generate an infinite recursive loop.
* When creating brand new PropertyExpensesAnnotation, it is necessary to call
* this method if one wants to fill the fields with default values.
*/
@Transient
public void setUpDefaults(){
retention = TimeDependentConstantsBusiness.getTimeDependentConstantValueByTimeDependentConstantType(TimeDependentConstantType.DEFAULT_RETENTION).getNumericalValue();
forCompany = PropertyIncomeAnnotation.DEFAULT_FOR_COMPANY;
vat = TimeDependentConstantsBusiness.getTimeDependentConstantValueByTimeDependentConstantType(TimeDependentConstantType.DEFAULT_VAT).getNumericalValue();
}
/**
* retain percentage in case a company issues a bill for the renting
*/
private Long retention;
/**
* VAT applied in the annotation
*/
protected Long vat;
/**
* Whether the annotation is a bill related to a company or not
*/
@Column(name = "for_company", nullable = false, columnDefinition = "TINYINT(1)")
private Boolean forCompany;
@Transient
public PropertyBook getPropertyBook() {
Book book = this.getBook();
if (book instanceof PropertyBook) {
PropertyBook propertyBook = (PropertyBook) book;
return propertyBook;
}
String message = "The PropertyIncomeAnnotation '"
+ this.toString() + "' has a Book which is not a PropertyBook.";
logger.error(message);
throw new AssetManagerRuntimeException(message);
}
/**
* @return the amount that should be declared yearly
* according to the Spanish fiscal system
*/
@Transient
public Double getDeclaredYearly() {
return getBaseImponibleYearly();
}
/**
* @return the VAT related to the annotation
* (zero in case the VAT does not applies to
* the annotation)
*/
@Transient
public Double getVat() {
if (getAppliesRetentionAndVAT()) {
return new Double(this.vat) / 100.0;
} else {
return 0.0; // default value in case there is no VAT
}
}
/**
* @return whether this annotation has the capability to
* select that it is related with a renting to a company or not
*/
@Transient
public Boolean getAppliesForCompany() {
return this.getPropertyBook().getProperty().getType()
.equals(PropertyType.TENEMENT);
}
/**
* @return whether this annotation applies retention and vat
*/
@Transient
public Boolean getAppliesRetentionAndVAT() {
return getDone()
&& (getPropertyBook().getProperty().getType().equals(
PropertyType.PREMISE) || (getPropertyBook().getProperty()
.getType().equals(PropertyType.TENEMENT) && getForCompany()));
}
/**
* @return the general tax base
* in the Spanish fiscal system.
*/
@Transient
public Double getBaseImponibleQuarterly() {
if (getAppliesRetentionAndVAT()) {
return getBaseImponibleForRetentionAndVat();
} else {
return 0.0;
}
}
@Transient
private Double getBaseImponibleForRetentionAndVat(){
Double amountFacturado = getAmount();
Double factor = (100.0 - this.getRetention() + this.getVat()) / 100.0;
return amountFacturado / factor;
}
/**
* @return the tax base for the yearly payment
* in the Spanish fiscal system.
*/
@Transient
public Double getBaseImponibleYearly() {
if(!getDone()){
// if not done, the tax base is zero
return 0.0;
}else{ // the income is done
if(getAppliesRetentionAndVAT()){
// if the retention and vat applies, means that we used the VAT and the retention
// in the quarterly, which implies that we should skip them in the yearly
return getBaseImponibleForRetentionAndVat();
}else{
// if the retention and the vat does not apply, then we just use the complete
// value ignoring the vat and the retention
return getAmount();
}
}
}
/**
* @return the retained amount that can be used by the
* yearly payment in the Spanish fiscal system
*/
@Transient
public Double getRetentionAmountYearly() {
if (getAppliesRetentionAndVAT()) {
// if the retention applies, then we return the tax base
// multiplied by the percentage of the retention
return getBaseImponibleForRetentionAndVat() * getRetention() / 100.0;
} else {
// if the retention does not apply,
// then there is just no retention to have into account
return 0.0;
}
}
public void setVat(Double vat) {
if (vat == null) {
this.vat = 0L;
} else {
if (vat < 0.0f) {
vat *= -1.0;
}
if(vat > 100.0){
vat = 100.0;
}
this.vat = Math.round(vat * 100.0);
}
}
public Boolean getForCompany() {
if (getAppliesForCompany()) {
return forCompany;
} else {
return false;
}
}
@NotifyChange(".")
public void setForCompany(Boolean forCompany) {
this.forCompany = forCompany;
}
public Double getRetention() {
if (getAppliesRetentionAndVAT()) {
if (this.retention == null) {
return 0.0;
} else {
return new Double(this.retention) / 100.0;
}
} else {
return 0.0;// default value when no retention is applied
}
}
public void setRetention(Double retention) {
if (retention == null) {
this.retention = 0L;
} else {
if (retention < 0.0) {
retention *= -1.0;
}
if (retention > 100.0) {
retention = 100.0;
}
this.retention = Math.round(retention * 100.0);
}
}
}