/* * Copyright (C) 2011 4th Line GmbH, Switzerland * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.fourthline.konto.shared.entity; import org.hibernate.annotations.Check; import org.fourthline.konto.shared.Constants; import org.seamless.gwt.validation.shared.EntityProperty; import org.fourthline.konto.shared.LedgerEntry; import org.fourthline.konto.shared.MonetaryAmount; import org.seamless.gwt.validation.shared.Validatable; import org.seamless.gwt.validation.shared.ValidationError; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.Transient; import javax.persistence.Version; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * @author Christian Bauer */ @Entity @Table(name = "SPLIT") @Check(constraints = "(ENTRY_AMOUNT = 0 and AMOUNT = 0) " + "or (ENTRY_AMOUNT > 0 and AMOUNT < 0) " + "or (ENTRY_AMOUNT < 0 and AMOUNT > 0)") public class Split implements LedgerEntry, Validatable, Comparable<Split> { public enum Property implements EntityProperty { id, accountId, description, entryAmount, amount, exchangeRate } @Id @GeneratedValue(generator = Constants.SEQUENCE_NAME) @Column(name = "SPLIT_ID") private Long id; @Version @Column(name = "OBJ_VERSION") private Long version; @Column(name = "ACCOUNT_ID", nullable = false) private Long accountId; @Column(name = "ENTRY_ID", nullable = false) private Long entryId; @Column(name = "DESCRIPTION", length = 255, nullable = false) private String description; @Column(name = "ENTRY_AMOUNT", nullable = false, precision = 15, scale = 3) private BigDecimal entryAmount; @Column(name = "AMOUNT", nullable = false, precision = 15, scale = 3) private BigDecimal amount; @Column(name = "ENTERED_ON", nullable = false) private Date enteredOn = new Date(); @Transient private Account account; @Transient private Entry entry; @Transient private MonetaryUnit entryMonetaryUnit; @Transient private MonetaryUnit monetaryUnit; public Split() { } public Split(MonetaryUnit entryMonetaryUnit, MonetaryUnit monetaryUnit) { this.entryMonetaryUnit = entryMonetaryUnit; this.monetaryUnit = monetaryUnit; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public Long getVersion() { return version; } public void setVersion(Long version) { this.version = version; } public Long getAccountId() { return accountId; } public void setAccountId(Long accountId) { this.accountId = accountId; } public Account getAccount() { return account; } public void setAccount(Account account) { this.account = account; } public Long getEntryId() { return entryId; } public void setEntryId(Long entryId) { this.entryId = entryId; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public MonetaryAmount getEntryAmount() { return new MonetaryAmount(getEntryMonetaryUnit(), entryAmount); } public void setEntryAmount(MonetaryAmount amount) { this.entryAmount = amount.getValue(); } public MonetaryAmount getAmount() { return new MonetaryAmount(getMonetaryUnit(), amount); } public void setAmount(MonetaryAmount amount) { this.amount = amount.getValue(); } public Date getEnteredOn() { return enteredOn; } public void setEnteredOn(Date enteredOn) { this.enteredOn = enteredOn; } public Entry getEntry() { return entry; } public void setEntry(Entry entry) { this.entry = entry; } public MonetaryUnit getEntryMonetaryUnit() { return entryMonetaryUnit; } public void setEntryMonetaryUnit(MonetaryUnit entryMonetaryUnit) { this.entryMonetaryUnit = entryMonetaryUnit; } public MonetaryUnit getMonetaryUnit() { return monetaryUnit; } public void setMonetaryUnit(MonetaryUnit monetaryUnit) { this.monetaryUnit = monetaryUnit; } @Override public List<ValidationError> validate(String group) { List<ValidationError> errors = new ArrayList(); if (getDescription() == null || getDescription().length() == 0) { errors.add(new ValidationError( getClass().getName(), Property.description, "Description is required." )); } boolean haveAmount = false; if (getAmount() == null) { errors.add(new ValidationError( getClass().getName(), Property.amount, "Amount is required." )); } else { haveAmount = getAmount().signum() != 0; } boolean haveEntryAmount = false; if (getEntryAmount() == null) { errors.add(new ValidationError( getClass().getName(), Property.entryAmount, "Entry amount is required." )); } else { haveEntryAmount = getEntryAmount().signum() != 0; } if (haveAmount && haveEntryAmount) { if (!((getAmount().signum() > 0 && getEntryAmount().signum() < 0) || (getAmount().signum() < 0 && getEntryAmount().signum() > 0))) { errors.add(new ValidationError( getClass().getName(), Property.amount, "Credit/debit amounts are not balanced." )); } } return errors; } @Override public int compareTo(Split split) { // Newest first if (getEnteredOn() == null || split.getEnteredOn() == null) return 0; return new Long(getEnteredOn().getTime()).compareTo(split.getEnteredOn().getTime()); } @Override public String toString() { return "Split: " + getId() + ", Entry: " + getEntryId() + ", " + getDescription() + ", " + getAmount() + ", " + getEntryAmount(); } }