Coverage Report - org.homeunix.thecave.buddi.model.impl.TransactionImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
TransactionImpl
0%
0/156
0%
0/166
3.556
 
 1  
 /*
 2  
  * Created on Jul 29, 2007 by wyatt
 3  
  */
 4  
 package org.homeunix.thecave.buddi.model.impl;
 5  
 
 6  
 import java.util.ArrayList;
 7  
 import java.util.Date;
 8  
 import java.util.HashMap;
 9  
 import java.util.List;
 10  
 import java.util.Map;
 11  
 
 12  
 import org.homeunix.thecave.buddi.i18n.BuddiKeys;
 13  
 import org.homeunix.thecave.buddi.model.Account;
 14  
 import org.homeunix.thecave.buddi.model.BudgetCategory;
 15  
 import org.homeunix.thecave.buddi.model.Document;
 16  
 import org.homeunix.thecave.buddi.model.ModelObject;
 17  
 import org.homeunix.thecave.buddi.model.Source;
 18  
 import org.homeunix.thecave.buddi.model.Split;
 19  
 import org.homeunix.thecave.buddi.model.Transaction;
 20  
 import org.homeunix.thecave.buddi.model.TransactionSplit;
 21  
 import org.homeunix.thecave.buddi.plugin.api.exception.InvalidValueException;
 22  
 import org.homeunix.thecave.buddi.plugin.api.util.TextFormatter;
 23  
 
 24  
 import ca.digitalcave.moss.common.DateUtil;
 25  
 
 26  
 /**
 27  
  * Default implementation of a Transaction.  You should not create this object directly; 
 28  
  * instead, please use the ModelFactory to create it, as this will ensure that all
 29  
  * required fields are correctly set.
 30  
  * @author wyatt
 31  
  *
 32  
  */
 33  0
 public class TransactionImpl extends ModelObjectImpl implements Transaction {
 34  
         protected Day date;
 35  
 //        protected String dateString;
 36  
         protected String description;
 37  
         protected String number;
 38  
         protected long amount;
 39  
         protected Source from;
 40  
         protected Source to;
 41  
         protected boolean deleted;
 42  
         protected boolean clearedFrom;
 43  
         protected boolean clearedTo;
 44  
         protected boolean reconciledFrom;
 45  
         protected boolean reconciledTo; 
 46  
         protected String memo;
 47  
 
 48  
         protected boolean scheduled;
 49  
 
 50  0
         protected final Map<String, Long> balances = new HashMap<String, Long>();
 51  
 
 52  
         protected List<TransactionSplit> fromSplits;// = new ArrayList<TransactionSplit>();
 53  
         protected List<TransactionSplit> toSplits;// = new ArrayList<TransactionSplit>();
 54  
 
 55  
 
 56  
         @Override
 57  
         public int compareTo(ModelObject arg0) {
 58  0
                 if (arg0 instanceof Transaction){
 59  0
                         Transaction t = (Transaction) arg0;
 60  
 
 61  
                         //For regular transactions, first we sort by date 
 62  0
                         if (!DateUtil.isSameDay(this.getDate(), t.getDate()))
 63  0
                                 return this.getDate().compareTo(t.getDate());
 64  
 
 65  
                         //Next we sort by debit / credit.  This is a nebulous beast, because of negative 
 66  
                         // amounts, credit accounts, splits, etc.
 67  
                         // We check the transaction source, and use some logic to determine if this means it
 68  
                         // is inflow or outflow. 
 69  0
                         if (this.isInflow() != t.isInflow()){
 70  0
                                 if (this.isInflow())
 71  0
                                         return -1;
 72  0
                                 return 1;
 73  
                         }
 74  
                         
 75  
                         //Next we sort on the number field
 76  0
                         String thisNumber = this.getNumber() == null ? "" : this.getNumber();
 77  0
                         String otherNumber = t.getNumber() == null ? "" : t.getNumber();
 78  0
                         if (!thisNumber.equals(otherNumber))
 79  0
                                 return thisNumber.compareTo(otherNumber);
 80  
 
 81  
                         //If everything else is the same, we sort on description.
 82  0
                         if (this.getDescription() != null && t.getDescription() != null && !this.getDescription().equals(t.getDescription())){
 83  0
                                 return this.getDescription().compareTo(t.getDescription());
 84  
                         }
 85  
                 }
 86  0
                 return super.compareTo(arg0);
 87  
         }
 88  
         public long getAmount() {
 89  0
                 return amount;
 90  
         }
 91  
         public long getBalance(String sourceUid) {
 92  0
                 if (balances.containsKey(sourceUid))
 93  0
                         return balances.get(sourceUid);
 94  0
                 return 0;
 95  
         }
 96  
         public Date getDate(){
 97  0
                 return date;
 98  
         }
 99  
         public String getDescription() {
 100  0
                 return description;
 101  
         }
 102  
         public Source getFrom() {
 103  0
                 return from;
 104  
         }
 105  
         public String getMemo() {
 106  0
                 return memo;
 107  
         }
 108  
         public String getNumber() {
 109  0
                 return number;
 110  
         }
 111  
         public Source getTo() {
 112  0
                 return to;
 113  
         }
 114  
         public boolean isClearedFrom() {
 115  0
                 return clearedFrom;
 116  
         }
 117  
         public boolean isClearedTo() {
 118  0
                 return clearedTo;
 119  
         }
 120  
         public boolean isInflow(){
 121  0
                 if (getFrom() instanceof BudgetCategory){
 122  0
                         return this.getAmount() >= 0;
 123  
                 }
 124  0
                 if (getTo() instanceof BudgetCategory){
 125  0
                         return this.getAmount() < 0;
 126  
                 }
 127  
 
 128  
                 //If neither sources are BudgetCategory, this is not an inflow.
 129  0
                 return false;
 130  
         }
 131  
         public boolean isReconciledFrom() {
 132  0
                 return reconciledFrom;
 133  
         }
 134  
         public boolean isReconciledTo() {
 135  0
                 return reconciledTo;
 136  
         }
 137  
         public boolean isScheduled() {
 138  0
                 return scheduled;
 139  
         }
 140  
         public void setAmount(long amount) {
 141  0
                 if (this.amount != amount)
 142  0
                         setChanged();
 143  0
                 this.amount = amount;
 144  0
         }
 145  
         public void setBalance(String sourceUid, long balance) {
 146  0
                 this.balances.put(sourceUid, balance);
 147  0
         }
 148  
         public void setClearedFrom(boolean cleared) {
 149  0
                 if (this.clearedFrom != cleared)
 150  0
                         setChanged();
 151  0
                 this.clearedFrom = cleared;
 152  
                 //If one of the To / From source is either
 153  
                 // a budget category or a Prepaid account,
 154  
                 // we set both of the flags to the same value.
 155  0
                 if (this.getTo() != null
 156  
                                 && this.getFrom() != null
 157  
                                 && !(this.getFrom() instanceof Split)
 158  
                                 && !(this.getTo() instanceof Split)
 159  
                                 && (this.getFrom() instanceof Account || this.getFrom() instanceof BudgetCategory) 
 160  
                                 && (this.getTo() instanceof Account || this.getTo() instanceof BudgetCategory)
 161  
                                 && (this.getTo() instanceof BudgetCategory
 162  
                                                 || this.getFrom() instanceof BudgetCategory
 163  
                                                 || ((Account) this.getTo()).getAccountType().getName().equals(TextFormatter.getTranslation(BuddiKeys.PREPAID_ACCOUNT))
 164  
                                                 || ((Account) this.getFrom()).getAccountType().getName().equals(TextFormatter.getTranslation(BuddiKeys.PREPAID_ACCOUNT)))){
 165  0
                         this.clearedTo = cleared;
 166  
                 }
 167  0
         }
 168  
         public void setClearedTo(boolean cleared) {
 169  0
                 if (this.clearedTo != cleared)
 170  0
                         setChanged();
 171  0
                 this.clearedTo = cleared;
 172  
                 //If one of the To / From source is either
 173  
                 // a budget category or a Prepaid account,
 174  
                 // we set both of the flags to the same value.
 175  0
                 if (this.getTo() != null
 176  
                                 && this.getFrom() != null
 177  
                                 && !(this.getFrom() instanceof Split)
 178  
                                 && !(this.getTo() instanceof Split)
 179  
                                 && (this.getTo() instanceof BudgetCategory
 180  
                                                 || this.getFrom() instanceof BudgetCategory
 181  
                                                 || ((Account) this.getTo()).getAccountType().getName().equals(TextFormatter.getTranslation(BuddiKeys.PREPAID_ACCOUNT))
 182  
                                                 || ((Account) this.getFrom()).getAccountType().getName().equals(TextFormatter.getTranslation(BuddiKeys.PREPAID_ACCOUNT)))){
 183  0
                         this.clearedFrom = cleared;
 184  
                 }
 185  0
         }
 186  
         public void setDate(Date date) {
 187  0
                 if (this.date != null && this.date.equals(date))
 188  0
                         setChanged();
 189  0
                 this.date = new Day(date);
 190  0
         }
 191  
         public void setDescription(String description) {
 192  0
                 if (this.description != null && !this.description.equals(description))
 193  0
                         setChanged();
 194  0
                 this.description = description;
 195  0
         }
 196  
         public void setFrom(Source from) {
 197  0
                 setChanged();
 198  0
                 this.from = from;
 199  0
                 if (this.fromSplits == null)
 200  0
                         this.fromSplits = new ArrayList<TransactionSplit>();
 201  0
                 this.fromSplits.clear();
 202  0
         }
 203  
         public void setMemo(String memo) {
 204  0
                 if (this.memo != null && !this.memo.equals(memo))
 205  0
                         setChanged();
 206  0
                 this.memo = memo;
 207  0
         }
 208  
         public void setNumber(String number) {
 209  0
                 if (this.number != null && !this.number.equals(number))
 210  0
                         setChanged();
 211  0
                 this.number = number;
 212  0
         }
 213  
         public void setReconciledFrom(boolean reconciled) {
 214  0
                 if (this.reconciledFrom != reconciled)
 215  0
                         setChanged();
 216  0
                 this.reconciledFrom = reconciled;
 217  
                 //If one of the To / From source is either
 218  
                 // a budget category or a Prepaid account,
 219  
                 // we set both of the flags to the same value.
 220  0
                 if (this.getTo() != null
 221  
                                 && this.getFrom() != null
 222  
                                 && (this.getFrom() instanceof Account || this.getFrom() instanceof BudgetCategory)
 223  
                                 && (this.getTo() instanceof Account || this.getTo() instanceof BudgetCategory)                                
 224  
                                 && (this.getTo() instanceof BudgetCategory
 225  
                                                 || this.getFrom() instanceof BudgetCategory
 226  
                                                 || ((Account) this.getTo()).getAccountType().getName().equals(TextFormatter.getTranslation(BuddiKeys.PREPAID_ACCOUNT))
 227  
                                                 || ((Account) this.getFrom()).getAccountType().getName().equals(TextFormatter.getTranslation(BuddiKeys.PREPAID_ACCOUNT)))){
 228  0
                         this.reconciledTo = reconciled;
 229  
                 }
 230  0
         }
 231  
         public void setReconciledTo(boolean reconciled) {
 232  0
                 if (this.reconciledTo != reconciled)
 233  0
                         setChanged();
 234  0
                 this.reconciledTo = reconciled;
 235  
                 //If one of the To / From source is either
 236  
                 // a budget category or a Prepaid account,
 237  
                 // we set both of the flags to the same value.
 238  0
                 if (this.getTo() != null
 239  
                                 && this.getFrom() != null
 240  
                                 && (this.getFrom() instanceof Account || this.getFrom() instanceof BudgetCategory)
 241  
                                 && (this.getTo() instanceof Account || this.getTo() instanceof BudgetCategory)
 242  
                                 && (this.getTo() instanceof BudgetCategory
 243  
                                                 || this.getFrom() instanceof BudgetCategory
 244  
                                                 || ((Account) this.getTo()).getAccountType().getName().equals(TextFormatter.getTranslation(BuddiKeys.PREPAID_ACCOUNT))
 245  
                                                 || ((Account) this.getFrom()).getAccountType().getName().equals(TextFormatter.getTranslation(BuddiKeys.PREPAID_ACCOUNT)))){
 246  0
                         this.reconciledFrom = reconciled;
 247  
                 }
 248  0
         }
 249  
         public void setScheduled(boolean scheduled) {
 250  0
                 this.scheduled = scheduled;
 251  0
         }
 252  
         public void setTo(Source to) {
 253  0
                 setChanged();
 254  0
                 this.to = to;
 255  0
                 if (this.toSplits == null)
 256  0
                         this.toSplits = new ArrayList<TransactionSplit>();
 257  0
                 this.toSplits.clear();
 258  0
         }
 259  
         public boolean isDeleted() {
 260  0
                 return deleted;
 261  
         }
 262  
 
 263  
         public void setDeleted(boolean deleted) {
 264  0
                 setChanged();
 265  0
                 this.deleted = deleted;
 266  0
         }
 267  
 
 268  
         public List<TransactionSplit> getToSplits() {
 269  0
                 return toSplits;
 270  
         }
 271  
 
 272  
         public void setToSplits(List<TransactionSplit> splits) throws InvalidValueException {
 273  0
                 setChanged();
 274  0
                 if (splits == this.toSplits) return;
 275  0
                 if (this.toSplits == null)
 276  0
                         this.toSplits = new ArrayList<TransactionSplit>();
 277  
                 
 278  0
                 this.toSplits.clear();
 279  
                 
 280  0
                 if (splits != null) {
 281  0
                         this.to = new SplitImpl();
 282  0
                         this.toSplits.addAll(splits);                        
 283  
                 }
 284  0
         }
 285  
         
 286  
         public List<TransactionSplit> getFromSplits() {
 287  0
                 return fromSplits;
 288  
         }
 289  
 
 290  
         public void setFromSplits(List<TransactionSplit> splits) throws InvalidValueException {
 291  0
                 setChanged();
 292  0
                 if (splits == this.toSplits) return;
 293  0
                 if (this.fromSplits == null)
 294  0
                         this.fromSplits = new ArrayList<TransactionSplit>();
 295  0
                 this.fromSplits.clear();
 296  
                 
 297  0
                 if (splits != null){
 298  0
                         this.from = new SplitImpl();
 299  0
                         this.fromSplits.addAll(splits);                        
 300  
                 }
 301  0
         }
 302  
 
 303  
         Transaction clone(Map<ModelObject, ModelObject> originalToCloneMap) throws CloneNotSupportedException {
 304  
 
 305  0
                 if (originalToCloneMap.get(this) != null)
 306  0
                         return (Transaction) originalToCloneMap.get(this);
 307  
 
 308  0
                 TransactionImpl t = new TransactionImpl();
 309  
 
 310  0
                 t.document = (Document) originalToCloneMap.get(document);
 311  0
                 t.amount = amount;
 312  0
                 t.clearedFrom = clearedFrom;
 313  0
                 t.clearedTo = clearedTo;
 314  0
                 t.date = new Day(date);
 315  0
                 t.deleted = deleted;
 316  0
                 t.description = description;
 317  0
                 t.from = (Source) ((SourceImpl) from).clone(originalToCloneMap);
 318  0
                 t.memo = memo;
 319  0
                 t.number = number;
 320  0
                 t.reconciledFrom = reconciledFrom;
 321  0
                 t.reconciledTo = reconciledTo;
 322  0
                 t.scheduled = scheduled;
 323  0
                 t.to = (Source) ((SourceImpl) to).clone(originalToCloneMap);
 324  0
                 if (this.toSplits == null)
 325  0
                         this.toSplits = new ArrayList<TransactionSplit>();
 326  0
                 if (this.fromSplits == null)
 327  0
                         this.fromSplits = new ArrayList<TransactionSplit>();
 328  0
                 if (t.toSplits == null)
 329  0
                         t.toSplits = new ArrayList<TransactionSplit>();
 330  0
                 if (t.fromSplits == null)
 331  0
                         t.fromSplits = new ArrayList<TransactionSplit>();                
 332  0
                 t.fromSplits.clear();
 333  0
                 for (TransactionSplit split : fromSplits) {
 334  0
                         t.fromSplits.add((TransactionSplit) ((TransactionSplitImpl) split).clone(originalToCloneMap));
 335  
                 }
 336  0
                 t.toSplits.clear();
 337  0
                 for (TransactionSplit split : toSplits) {
 338  0
                         t.toSplits.add((TransactionSplit) ((TransactionSplitImpl) split).clone(originalToCloneMap));
 339  
                 }
 340  0
                 t.modifiedTime = new Time(modifiedTime);
 341  
                 
 342  0
                 originalToCloneMap.put(this, t);
 343  
 
 344  0
                 return t;
 345  
         }
 346  
         
 347  
         @Override
 348  
         public String toString() {
 349  0
                 return getDescription() + " " + getAmount() + " (" + getFrom() + " -> " + getTo() + ")";
 350  
         }
 351  
 }