Coverage Report - org.homeunix.thecave.buddi.plugin.builtin.report.AverageIncomeExpenseByCategory
 
Classes in this File Line Coverage Branch Coverage Complexity
AverageIncomeExpenseByCategory
4%
4/96
0%
0/66
5.556
AverageIncomeExpenseByCategory$1
0%
0/6
0%
0/4
5.556
 
 1  
 /*
 2  
  * Created on Sep 14, 2006 by wyatt
 3  
  */
 4  
 package org.homeunix.thecave.buddi.plugin.builtin.report;
 5  
 
 6  
 import java.util.Collections;
 7  
 import java.util.Comparator;
 8  
 import java.util.Date;
 9  
 import java.util.List;
 10  
 
 11  
 import org.homeunix.thecave.buddi.i18n.BuddiKeys;
 12  
 import org.homeunix.thecave.buddi.i18n.keys.BudgetCategoryTypes;
 13  
 import org.homeunix.thecave.buddi.i18n.keys.PluginReportDateRangeChoices;
 14  
 import org.homeunix.thecave.buddi.plugin.api.BuddiReportPlugin;
 15  
 import org.homeunix.thecave.buddi.plugin.api.model.ImmutableBudgetCategory;
 16  
 import org.homeunix.thecave.buddi.plugin.api.model.ImmutableDocument;
 17  
 import org.homeunix.thecave.buddi.plugin.api.model.ImmutableSplit;
 18  
 import org.homeunix.thecave.buddi.plugin.api.model.ImmutableTransaction;
 19  
 import org.homeunix.thecave.buddi.plugin.api.model.ImmutableTransactionSplit;
 20  
 import org.homeunix.thecave.buddi.plugin.api.util.HtmlHelper;
 21  
 import org.homeunix.thecave.buddi.plugin.api.util.HtmlPage;
 22  
 import org.homeunix.thecave.buddi.plugin.api.util.TextFormatter;
 23  
 
 24  
 import ca.digitalcave.moss.common.DateUtil;
 25  
 import ca.digitalcave.moss.common.Version;
 26  
 import ca.digitalcave.moss.swing.MossDocumentFrame;
 27  
 
 28  
 /**
 29  
  * Built-in plugin.  Feel free to use this as an example on how to make
 30  
  * report plugins
 31  
  * 
 32  
  * @author wyatt
 33  
  *
 34  
  */
 35  2977
 public class AverageIncomeExpenseByCategory extends BuddiReportPlugin {
 36  
         
 37  
         public static final long serialVersionUID = 0;
 38  
         
 39  
         public Version getMaximumVersion() {
 40  0
                 return null; //This is integrated, so there is no need to pick this.
 41  
         }
 42  
 
 43  
         public Version getMinimumVersion() {
 44  0
                 return null;
 45  
         }
 46  
 
 47  
         public boolean isPluginActive() {
 48  3025
                 return true;
 49  
         }
 50  
 
 51  
         @Override
 52  
         public HtmlPage getReport(ImmutableDocument model, MossDocumentFrame callingFrame, Date startDate, Date endDate) {
 53  0
                 StringBuilder sb = HtmlHelper.getHtmlHeader(getName(), null, startDate, endDate);
 54  
 
 55  0
                 List<ImmutableBudgetCategory> categories = model.getImmutableBudgetCategories();
 56  0
                 Collections.sort(categories, new Comparator<ImmutableBudgetCategory>(){
 57  
                         public int compare(ImmutableBudgetCategory o1, ImmutableBudgetCategory o2) {
 58  
                                 //First we sort by income
 59  0
                                 if (o1.isIncome() != o2.isIncome()){
 60  0
                                         if (o1.isIncome()){
 61  0
                                                 return -1;
 62  
                                         }
 63  
                                         else {
 64  0
                                                 return 1;
 65  
                                         }
 66  
                                 }
 67  
                                                                 
 68  
                                 //Finally, we sort by Category Name
 69  0
                                 return o1.toString().compareTo(o2.toString());
 70  
                         }
 71  
                 });
 72  
                 
 73  0
                 sb.append("<h1>").append(TextFormatter.getTranslation(BuddiKeys.REPORT_SUMMARY)).append("</h1>\n");
 74  0
                 sb.append("<table class='main'>\n");
 75  
                 
 76  0
                 sb.append("<tr><th>");
 77  0
                 sb.append(TextFormatter.getTranslation(BuddiKeys.NAME));
 78  0
                 sb.append("</th><th>");
 79  0
                 sb.append(TextFormatter.getTranslation(BuddiKeys.ACTUAL));
 80  0
                 sb.append("</th><th>");
 81  0
                 sb.append(TextFormatter.getTranslation(BuddiKeys.AVERAGE));
 82  0
                 sb.append(" / ");
 83  0
                 sb.append(TextFormatter.getTranslation(model.getBudgetCategoryType(BudgetCategoryTypes.BUDGET_CATEGORY_TYPE_MONTH).getName()));
 84  0
                 sb.append("</th></tr>\n");
 85  
                 
 86  0
                 long totalActual = 0, totalAverage = 0;
 87  
                 
 88  0
                 for (ImmutableBudgetCategory c : categories){
 89  
                         
 90  
                         
 91  0
                         List<ImmutableTransaction> transactions = model.getImmutableTransactions(c, startDate, endDate);
 92  0
                         long actual = 0;
 93  0
                         for (ImmutableTransaction transaction : transactions) {
 94  0
                                 if (!transaction.isDeleted()){
 95  
                                         //Figure out the actual amounts
 96  0
                                         if (transaction.getFrom().equals(c) || transaction.getTo().equals(c)){
 97  0
                                                 actual += transaction.getAmount();                                                
 98  
                                         }
 99  
                                         
 100  0
                                         for (ImmutableTransactionSplit split : transaction.getImmutableToSplits()) {
 101  0
                                                 if (split.getSource().equals(c)){
 102  0
                                                         actual += split.getAmount();
 103  
                                                 }
 104  
                                         }
 105  0
                                         for (ImmutableTransactionSplit split : transaction.getImmutableFromSplits()) {
 106  0
                                                 if (split.getSource().equals(c)){
 107  0
                                                         actual -= split.getAmount();
 108  
                                                 }
 109  
                                         }
 110  
 
 111  
                                         //Add to total for non-split transactions
 112  0
                                         if (transaction.getTo() instanceof ImmutableBudgetCategory){
 113  0
                                                 totalActual -= transaction.getAmount();
 114  
                                         }
 115  0
                                         else if (transaction.getFrom() instanceof ImmutableBudgetCategory){
 116  0
                                                 totalActual += transaction.getAmount();
 117  
                                         }
 118  
 
 119  
                                         //Add to total for split transactions
 120  0
                                         if (transaction.getTo() instanceof ImmutableSplit){
 121  0
                                                 for (ImmutableTransactionSplit split : transaction.getImmutableToSplits()) {
 122  0
                                                         if (split.getSource().equals(c)){
 123  0
                                                                 totalActual -= split.getAmount();
 124  
                                                         }
 125  
                                                 }
 126  
                                         }
 127  0
                                         if (transaction.getFrom() instanceof ImmutableSplit){
 128  0
                                                 for (ImmutableTransactionSplit split : transaction.getImmutableFromSplits()) {
 129  0
                                                         if (split.getSource().equals(c)){
 130  0
                                                                 totalActual += split.getAmount();
 131  
                                                         }
 132  
                                                 }
 133  
                                         }
 134  
                                 }
 135  
                         }
 136  
                         //////the following code has been modified for the average calculation bug:
 137  
                         long average;
 138  
                        
 139  0
                        if(isQuarter(startDate, endDate,model.getBudgetCategoryType(BudgetCategoryTypes.BUDGET_CATEGORY_TYPE_MONTH).getDaysInPeriod(endDate)))
 140  0
                            average = (long) ((double) actual / 3.0);
 141  
                        else 
 142  0
                         average = (long) ((double) actual / (double) DateUtil.getDaysBetween(startDate, endDate, true) * 
 143  
                                 model.getBudgetCategoryType(BudgetCategoryTypes.BUDGET_CATEGORY_TYPE_MONTH).getDaysInPeriod(endDate));
 144  
                         //////////////////
 145  0
                         if (c.isIncome()){
 146  0
                                 totalAverage += average;
 147  
                         }
 148  
                         else {
 149  0
                                 totalAverage -= average;
 150  
                         }
 151  
                         
 152  
 
 153  0
                         if (transactions.size() > 0){                                
 154  0
                                 sb.append("<tr>");
 155  0
                                 sb.append("<td>");
 156  0
                                 sb.append(TextFormatter.getTranslation(c.toString()));
 157  0
                                 sb.append("</td><td class='right" + (TextFormatter.isRed(c, actual) ? " red'" : "'") + ">");
 158  0
                                 sb.append(TextFormatter.getFormattedCurrency(actual));
 159  0
                                 sb.append("</td><td class='right" + (TextFormatter.isRed(c, average) ? " red'" : "'") + "'>");
 160  0
                                 sb.append(TextFormatter.getFormattedCurrency(average));                                
 161  0
                                 sb.append("</td></tr>\n");
 162  
                         }
 163  0
                 }
 164  
                 
 165  0
                 sb.append("<tr><th>");
 166  0
                 sb.append(TextFormatter.getTranslation(BuddiKeys.TOTAL));
 167  0
                 sb.append("</th><th class='right" + (TextFormatter.isRed(totalActual) ? " red'" : "'") + "'>");
 168  0
                 sb.append(TextFormatter.getFormattedCurrency(totalActual));
 169  0
                 sb.append("</th><th class='right" + (TextFormatter.isRed(totalAverage) ? " red'" : "'") + "'>");
 170  0
                 sb.append(TextFormatter.getFormattedCurrency(totalAverage));
 171  0
                 sb.append("</th></tr>\n");
 172  
 
 173  0
                 sb.append("</table>\n\n");
 174  
                 
 175  0
                 sb.append("<hr>\n");
 176  
                 
 177  0
                 sb.append("<h1>").append(TextFormatter.getTranslation(BuddiKeys.REPORT_DETAILS)).append("</h1>\n");
 178  
                 
 179  0
                 for (ImmutableBudgetCategory bc : categories){
 180  0
                         List<ImmutableTransaction> transactions = model.getImmutableTransactions(bc, startDate, endDate);
 181  
                         
 182  
                         
 183  0
                         if (transactions.size() > 0){
 184  0
                                 sb.append(bc.isIncome() ? "<h2>" : "<h2 class='red'>");
 185  0
                                 sb.append(TextFormatter.getTranslation(bc.toString()));
 186  0
                                 sb.append("</h2>\n");
 187  
 
 188  0
                                 sb.append(HtmlHelper.getHtmlTransactionHeader());
 189  
 
 190  
 
 191  0
                                 for (ImmutableTransaction t : transactions) {
 192  0
                                         if (!t.isDeleted())
 193  0
                                                 sb.append(HtmlHelper.getHtmlTransactionRow(t, bc));
 194  
                                 }
 195  
 
 196  0
                                 sb.append(HtmlHelper.getHtmlTransactionFooter());
 197  
                         }
 198  0
                 }
 199  
                 
 200  0
                 sb.append(HtmlHelper.getHtmlFooter());
 201  
         
 202  0
                 return new HtmlPage(sb.toString(), null);
 203  
         }
 204  
         
 205  
         public String getName() {
 206  0
                 return TextFormatter.getTranslation(BuddiKeys.REPORT_TITLE_AVERAGE_INCOME_AND_EXPENSES_BY_CATEGORY);
 207  
         }
 208  
 
 209  
         public String getDescription() {
 210  3025
                 return BuddiKeys.REPORT_DESCRIPTION_AVERAGE_INCOME_AND_EXPENSES_BY_CATEGORY.toString();
 211  
         }
 212  
         
 213  
         @Override
 214  
         public PluginReportDateRangeChoices getDateRangeChoice() {
 215  3025
                 return PluginReportDateRangeChoices.INTERVAL;
 216  
         }
 217  
         
 218  
         ////////////////////////////////////////////////////The following code has been added to fix the average calculations bug
 219  
         public boolean isQuarter(Date startDate, Date endDate , long days)
 220  
         {
 221  0
               if(!DateUtil.isSameYear(startDate, endDate))
 222  0
                   return false;
 223  0
               if(DateUtil.getDay(startDate) != 1)
 224  0
                   return false;
 225  0
               if(DateUtil.getDay(endDate) != days)
 226  0
                   return false;
 227  0
               if(DateUtil.getMonthsBetween(startDate, endDate, false) != 2)
 228  0
                   return false;
 229  0
               return true;
 230  
         }
 231  
         ////////////////////////////////////////////////////
 232  
 }