Logo Search packages:      
Sourcecode: qbankmanager version File versions  Download package

categoryreport.cpp

/***************************************************************************
 $RCSfile: categoryreport.cpp,v $
                             -------------------
    cvs         : $Id: categoryreport.cpp,v 1.1 2005/09/01 07:27:38 aquamaniac Exp $
    begin       : Mon Mar 01 2004
    copyright   : (C) 2004 by Martin Preuss
    email       : martin@libchipcard.de

 ***************************************************************************
 *          Please see toplevel file COPYING for license details           *
 ***************************************************************************/



#ifdef HAVE_CONFIG_H
# include <config.h>
#endif


#define COLUMN_EMPTY                0
#define COLUMN_LOCAL_BANKCODE       1
#define COLUMN_LOCAL_ACCOUNTNUMBER  2
#define COLUMN_LOCAL_NAME           3
#define COLUMN_REMOTE_BANKCODE      4
#define COLUMN_REMOTE_ACCOUNTNUMBER 5
#define COLUMN_REMOTE_NAME          6
#define COLUMN_UNIQUE_ID            7
#define COLUMN_VALUTA_DATE          8
#define COLUMN_DATE                 9
#define COLUMN_VALUE                10
#define COLUMN_CUST_REF             11
#define COLUMN_BANK_REF             12
#define COLUMN_PRIMANOTA            13
#define COLUMN_REMOTE_NAME_PURPOSE  14
#define COLUMN_CATEGORY             15
#define COLUMN_PURPOSE              16

#define COLUMN_LOCAL_ACCOUNT        17
#define COLUMN_REMOTE_ACCOUNT       18

#define COLUMN_PAYEE                19


#include "kbanking.h"
#include "categoryreport.h"
#include "editcategoryreport.h"
#include "transfinder.h"
#include "transaction.h"
#include "account.h"

#include <qwidget.h>
#include <qstring.h>
#include <qmessagebox.h>
#include <qwidget.h>

#define I18N_NOOP(msg) msg



CategoryReport::CategoryReport(KBanking *app)
:Report(app, "CategoryReport"){


}



CategoryReport::~CategoryReport(){
}



QString CategoryReport::shortDescription(){
  return QWidget::tr("Reports per categories");
}



QString CategoryReport::longDescription(){
  return QWidget::tr
    (
     "<qt>"
     "This module allows creating of category reports."
     "</qt>"
    );
}



bool CategoryReport::initProfile(GWEN_DB_NODE *dbProfile, QWidget *parent){
  EditCategoryReport w(dbProfile, parent);

  w.setCaption(QWidget::tr("Create new profile"));
  if (w.exec()!=QDialog::Accepted)
    return false;

  return true;
}



bool CategoryReport::editProfile(GWEN_DB_NODE *dbProfile, QWidget *parent){
  EditCategoryReport w(dbProfile, parent);

  w.setCaption(QWidget::tr("Edit profile"));
  if (w.exec()!=QDialog::Accepted)
    return false;

  return true;
}




QString CategoryReport::handleTransaction(GWEN_DB_NODE *dbProfile,
                                          QWidget *parent,
                                          RefPointer<Transaction> t) {
  QString qs;
  std::string s;

  // handle transactions
  int i;

  qs="<tr>";

  for (i=0; ; i++) {
    const std::list<std::string> sl;
    std::list<std::string>::const_iterator sit;
    const GWEN_TIME *ti;
    const AB_VALUE *v;
    int j, k;

    j=GWEN_DB_GetIntValue(dbProfile, "column", i, 0);
    if (!j)
      break;
    switch(j) {
    case COLUMN_LOCAL_BANKCODE:
      qs+="<td>";
      qs+=QString::fromUtf8(t.ref().getLocalBankCode().c_str());
      break;

    case COLUMN_LOCAL_ACCOUNTNUMBER:
      qs+="<td>";
      qs+=QString::fromUtf8(t.ref().getLocalAccountNumber().c_str());
      break;

    case COLUMN_LOCAL_NAME:
      qs+="<td>";
      qs+=QString::fromUtf8(t.ref().getLocalName().c_str());
      break;

    case COLUMN_REMOTE_BANKCODE:
      qs+="<td>";
      qs+=QString::fromUtf8(t.ref().getRemoteBankCode().c_str());
      break;

    case COLUMN_REMOTE_ACCOUNTNUMBER:
      qs+="<td>";
      qs+=QString::fromUtf8(t.ref().getRemoteAccountNumber().c_str());
      break;

    case COLUMN_REMOTE_NAME:
      qs+="<td>";
      k=0;
      for (sit=t.ref().getRemoteName().begin();
           sit!=t.ref().getRemoteName().end();
           sit++) {
        if (k++)
          qs+="<br>";
        qs+=QString::fromUtf8((*sit).c_str());
      }
      break;

    case COLUMN_UNIQUE_ID:
      qs+="<td>";
      qs+=QString::number(t.ref().getTransactionId());
      break;

    case COLUMN_VALUTA_DATE:
      qs+="<td>";
      ti=t.ref().getValutaDate();
      if (ti) {
        GWEN_BUFFER *tbuf;

        tbuf=GWEN_Buffer_new(0, 32, 0, 1);
        if (!GWEN_Time_toString(ti,
                                tr("YYYY/MM/DD").latin1(),
                                tbuf)) {
          qs+=QString::fromUtf8(GWEN_Buffer_GetStart(tbuf));
        }
        GWEN_Buffer_free(tbuf);
      }
      break;

    case COLUMN_DATE:
      qs+="<td>";
      ti=t.ref().getDate();
      if (ti) {
        GWEN_BUFFER *tbuf;

        tbuf=GWEN_Buffer_new(0, 32, 0, 1);
        if (!GWEN_Time_toString(ti,
                                tr("YYYY/MM/DD").latin1(),
                                tbuf)) {
          qs+=QString::fromUtf8(GWEN_Buffer_GetStart(tbuf));
        }
        GWEN_Buffer_free(tbuf);
      }
      break;

    case COLUMN_VALUE:
      qs+="<td align=\"right\">";
      v=t.ref().getValue();
      if (v) {
        char numbuf[32];

        if (GWEN_DB_GetIntValue(dbProfile, "useColours", 0, 0)) {
          if (AB_Value_GetValue(v)>0)
            qs+="<font color=\"dark green\">";
          else
            qs+="<font color=red>";
        }
#if !defined(__GNUC__) && defined(WIN32)
        // This is MSVC compiler which doesnt have snprintf()
        sprintf(numbuf, "%.2lf", AB_Value_GetValue(v));
#else
        snprintf(numbuf, sizeof(numbuf), "%.2lf", AB_Value_GetValue(v));
#endif
        qs+=numbuf;
        qs+=" ";
        qs+=AB_Value_GetCurrency(v);
        if (GWEN_DB_GetIntValue(dbProfile, "useColours", 0, 0))
          qs+="</font>";
      }
      break;

    case COLUMN_CUST_REF:
      qs+="<td>";
      qs+=QString::fromUtf8(t.ref().getCustomerReference().c_str());
      break;

    case COLUMN_BANK_REF:
      qs+="<td>";
      qs+=QString::fromUtf8(t.ref().getBankReference().c_str());
      break;

    case COLUMN_PRIMANOTA:
      qs+="<td>";
      qs+=QString::fromUtf8(t.ref().getPrimanota().c_str());
      break;

    case COLUMN_REMOTE_NAME_PURPOSE:
      qs+="<td>";
      k=0;
      for (sit=t.ref().getRemoteName().begin();
           sit!=t.ref().getRemoteName().end();
           sit++) {
        if (k++)
          qs+="<br>";
        qs+=QString::fromUtf8((*sit).c_str());
      }
      if (k)
        qs+="<br>";
      for (sit=t.ref().getPurpose().begin();
           sit!=t.ref().getPurpose().end();
           sit++) {
        if (k++)
          qs+="<br>";
        qs+=QString::fromUtf8((*sit).c_str());
      }
      break;

    case COLUMN_CATEGORY:
      qs+="<td>";
      qs+=QString::fromUtf8(t.ref().getCategory().c_str());
      break;

    case COLUMN_PURPOSE:
      qs+="<td>";
      k=0;
      for (sit=t.ref().getPurpose().begin();
           sit!=t.ref().getPurpose().end();
           sit++) {
        if (k++)
          qs+="<br>";
        qs+=QString::fromUtf8((*sit).c_str());
      }
      break;


    case COLUMN_LOCAL_ACCOUNT:
      qs+="<td>";
      qs+=QString::fromUtf8(t.ref().getLocalBankCode().c_str());
      qs+="<br>";
      qs+=QString::fromUtf8(t.ref().getLocalAccountNumber().c_str());
      break;

    case COLUMN_REMOTE_ACCOUNT:
      qs+="<td>";
      qs+=QString::fromUtf8(t.ref().getRemoteBankCode().c_str());
      qs+="<br>";
      qs+=QString::fromUtf8(t.ref().getRemoteAccountNumber().c_str());
      break;

    case COLUMN_PAYEE:
      qs+="<td>";
      s=t.ref().getPayee();
      if (!s.empty()) {
        Payee *p;

        p=app()->findPayeeById(s.c_str());
        if (p)
          qs+=QString::fromUtf8(p->name().c_str());
      }
      break;

    case COLUMN_EMPTY:
    default:
      qs+="<td>";
      break;
    } // switch
    qs+="</td>";
  } // for

  qs+="</tr>\n";

  return qs;
}



QString CategoryReport::handleMonth(GWEN_DB_NODE *dbProfile,
                                    QWidget *parent,
                                    Report::Month *m){
  QString qs;
  int i;
  std::list<RefPointer<Transaction> > tl;
  std::list<RefPointer<Transaction> >::iterator it;
  const char *monthNames[12]={
    I18N_NOOP("January"), I18N_NOOP("February"), I18N_NOOP("March"),
    I18N_NOOP("April"), I18N_NOOP("May"), I18N_NOOP("June"),
    I18N_NOOP("July"), I18N_NOOP("August"), I18N_NOOP("September"),
    I18N_NOOP("October"), I18N_NOOP("November"), I18N_NOOP("December")};

  qs=tr("<h3>Transactions for %1 %2</h3>\n")
    .arg(tr(monthNames[m->getMonth()]))
    .arg(m->getYear());

  if (GWEN_DB_GetIntValue(dbProfile, "border", 0, 0))
    qs+=tr("<table border=\"1\">\n");
  else
    qs+=tr("<table>\n");
  qs+=tr("<tr>");

  for (i=0; ; i++) {
    int j;

    j=GWEN_DB_GetIntValue(dbProfile, "column", i, 0);
    if (!j)
      break;
    qs+="<th align=\"center\">";
    switch(j) {
    case COLUMN_LOCAL_BANKCODE:       qs+=tr("Local<br>Bank"); break;
    case COLUMN_LOCAL_ACCOUNTNUMBER:  qs+=tr("Local<br>Account"); break;
    case COLUMN_LOCAL_NAME:           qs+=tr("Local<br>Name"); break;
    case COLUMN_REMOTE_BANKCODE:      qs+=tr("Remote<br>Bank"); break;
    case COLUMN_REMOTE_ACCOUNTNUMBER: qs+=tr("Remote<br>Account"); break;
    case COLUMN_REMOTE_NAME:          qs+=tr("Remote<br>Name"); break;
    case COLUMN_UNIQUE_ID:            qs+=tr("Unique<br>Id"); break;
    case COLUMN_VALUTA_DATE:          qs+=tr("Valuta<br>Date"); break;
    case COLUMN_DATE:                 qs+=tr("Date"); break;
    case COLUMN_VALUE:                qs+=tr("Value"); break;
    case COLUMN_CUST_REF:             qs+=tr("Customer<br>Reference"); break;
    case COLUMN_BANK_REF:             qs+=tr("Bank<br>Reference"); break;
    case COLUMN_PRIMANOTA:            qs+=tr("Primanota"); break;
    case COLUMN_REMOTE_NAME_PURPOSE:  qs+=tr("Remote Name<br>Purpose"); break;
    case COLUMN_CATEGORY:             qs+=tr("Category"); break;
    case COLUMN_PURPOSE:              qs+=tr("Purpose"); break;
    case COLUMN_LOCAL_ACCOUNT:        qs+=tr("Local<br>Account"); break;
    case COLUMN_REMOTE_ACCOUNT:       qs+=tr("Remote<br>Account"); break;
    case COLUMN_PAYEE:                qs+=tr("Payee"); break;
    case COLUMN_EMPTY:
    default:
      break;
    } // switch
    qs+="</th>";
  } // for
  qs+="</tr>\n";

  // handle transactions
  m->gatherTransactions(tl);
  sortTransactions(tl);
  for (it=tl.begin(); it!=tl.end(); it++) {
    qs+=handleTransaction(dbProfile, parent, *it);
  }

  qs+="</table>";

  return qs;
}



QString CategoryReport::handleCategory(GWEN_DB_NODE *dbProfile,
                                       QWidget *parent,
                                       Report::CategoryData *cd){
  Category *cat;
  std::string name;
  QString qs;
  std::list<Year*>::iterator yit;
  std::list<RefPointer<Transaction> >::iterator it;

  cat=cd->getCategory();

  sortYears(cd->years());

  for (yit=cd->years().begin();
       yit!=cd->years().end();
       yit++) {
    std::list<Month*>::iterator mit;

    sortMonths((*yit)->months());
    for (mit=(*yit)->months().begin();
         mit!=(*yit)->months().end();
         mit++) {
      qs+=handleMonth(dbProfile, parent, *mit);
    }
  } // for

  return qs;
}



Report::CategoryData*
CategoryReport::_findCategoryData(std::list<Report::CategoryData*> &cdl,
                                  const char *id) {
  std::list<Report::CategoryData*>::iterator cit;

  for (cit=cdl.begin(); cit!=cdl.end(); cit++) {
    if (strcasecmp((*cit)->getCategory()->getId().c_str(),
                   id)==0)
      return *cit;
  } // for

  return 0;
}



QString CategoryReport::_handleRealCategory(GWEN_DB_NODE *dbProfile,
                                            QWidget *parent,
                                            std::list<CategoryData*> cdl,
                                            Category *cat,
                                            AB_VALUE *val,
                                            int level) {
  CategoryData *cd;
  std::list<Category*>::iterator it;
  QString res;
  QString childrenRes;
  AB_VALUE *catVal;
  bool showTrans;
  bool showEmpty;

  showTrans=(GWEN_DB_GetIntValue(dbProfile, "showTrans", 0, 0)!=0);
  showEmpty=(GWEN_DB_GetIntValue(dbProfile, "showEmpty", 0, 0)!=0);

  catVal=AB_Value_new(0.0, 0);
  cd=_findCategoryData(cdl, cat->getId().c_str());
  if (cd) {
    if (showTrans) {
      res+=tr("<h2>Category <i>%1</i></h2>\n")
        .arg(QString::fromUtf8(cat->getPath().c_str()));
      res+="<br>";

      res+=handleCategory(dbProfile, parent, cd);
    }
    AB_Value_AddValue(catVal, cd->getValue());
  }

  for (it=cat->getChildren().begin();
       it!=cat->getChildren().end();
       it++) {
    childrenRes+=_handleRealCategory(dbProfile, parent, cdl, *it, catVal,
                                     level+1);
  }

  res+=childrenRes;

  if (cd || !childrenRes.isEmpty() || !showTrans || showEmpty) {
    char numbuf[32];
    QString qs;

#if !defined(__GNUC__) && defined(WIN32)
    // This is MSVC compiler which doesnt have snprintf()
    sprintf(numbuf, "%.2lf", AB_Value_GetValue(catVal));
#else
    snprintf(numbuf, sizeof(numbuf), "%.2lf", AB_Value_GetValue(catVal));
#endif
    qs=numbuf;

    if (showTrans) {
      res+="<hr>";
      res+=QWidget::tr("Summary for category <i>%1</i>: <b>%2</b>")
        .arg(QString::fromUtf8(cat->getPath().c_str()))
        .arg(qs);
    }
    else {
      if (showEmpty || !AB_Value_IsZero(catVal)) {
        res+="<tr><td>";
        res+=QString::fromUtf8(cat->getPath().c_str());
        res+="</td><td align=right>";
        res+=qs;
        res+="</td></tr>";
      }
    }
  }

  AB_Value_AddValue(val, catVal);
  AB_Value_free(catVal);
  return res;
}



bool CategoryReport::useProfile(GWEN_DB_NODE *dbProfile, QWidget *parent){
  QString qs;
  std::list<RefPointer<Transaction> > tl;
  std::list<RefPointer<Transaction> >::iterator it;
  std::list<CategoryData*> cdl;
  std::list<CategoryData*>::iterator cit;
  std::list<Category*>::const_iterator clit;
  bool showTrans;
  GWEN_TIME *minDate=0;
  GWEN_TIME *maxDate=0;

  showTrans=(GWEN_DB_GetIntValue(dbProfile, "showTrans", 0, 0)!=0);

  TransactionFinder tf(app(),
                       app()->getTransactionMatcherRules(),
                       "default",
                       TRANSFINDER_FLAGS_USE_CATEGORY |
                       TRANSFINDER_FLAGS_EXT_PAYEES,
                       parent, "TransactionFinder",
                       true);
  tf.init();
  if (tf.exec()!=QDialog::Accepted) {
    DBG_WARN(0, "User aborted");
    return false;
  }
  app()->setTransactionMatcherRules(tf.getRules());
  tl=tf.getMatchingTransactions();
  tf.fini();

  if (tl.empty()) {
    DBG_ERROR(0, "No transactions");
    return false;
  }

  for (it=tl.begin(); it!=tl.end(); it++) {
    const GWEN_TIME *ti;

    DBG_ERROR(0, "Adding Transaction");
    ti=(*it).ref().getDate();
    if (!ti)
      ti=(*it).ref().getValutaDate();
    if (ti) {
      if (!minDate)
        minDate=GWEN_Time_dup(ti);
      else {
        if (GWEN_Time_Diff(minDate, ti)>0) {
          GWEN_Time_free(minDate);
          minDate=GWEN_Time_dup(ti);
        }
      }
      if (!maxDate)
        maxDate=GWEN_Time_dup(ti);
      else {
        if (GWEN_Time_Diff(ti, maxDate)>0) {
          GWEN_Time_free(maxDate);
          maxDate=GWEN_Time_dup(ti);
        }
      }
    }
    addTransaction(cdl, *it);
  } // for

  app()->sortCategories();

  DBG_ERROR(0, "Printing report...");
  qs="<html>";

  qs+="<h1>";
  if (minDate || maxDate) {
    std::string tmpl=QBanking::QStringToUtf8String(QWidget::tr("YYYY/MM/DD"));
    QString fromDate;
    QString toDate;

    if (minDate) {
      GWEN_BUFFER *tbuf;

      tbuf=GWEN_Buffer_new(0, 32, 0, 1);
      GWEN_Time_toString(minDate, tmpl.c_str(), tbuf);
      fromDate=QString::fromUtf8(GWEN_Buffer_GetStart(tbuf));
      GWEN_Buffer_free(tbuf);
    }
    if (maxDate) {
      GWEN_BUFFER *tbuf;

      tbuf=GWEN_Buffer_new(0, 32, 0, 1);
      GWEN_Time_toString(maxDate, tmpl.c_str(), tbuf);
      toDate=QString::fromUtf8(GWEN_Buffer_GetStart(tbuf));
      GWEN_Buffer_free(tbuf);
    }

    if (minDate && maxDate) {
      qs+=QWidget::tr("Category Report (%1 - %2)")
        .arg(fromDate)
        .arg(toDate);
    }
    else if (minDate && !maxDate) {
      qs+=QWidget::tr("Category Report (%1 -)")
        .arg(fromDate);
    }
    else if (!minDate && maxDate) {
      qs+=QWidget::tr("Category Report (- %1)")
        .arg(toDate);
    }
  }
  else
    qs+=QWidget::tr("Category Report");
  qs+="</h1>";

  if (!showTrans) {
    if (GWEN_DB_GetIntValue(dbProfile, "border", 0, 0))
      qs+="<table border=\"1\">";
    else
      qs+="<table>";
    qs+="<tr><th><b>";
    qs+=QWidget::tr("Category");
    qs+="</b></th><th><b>";
    qs+=QWidget::tr("Amount");
    qs+="</b></th></tr>\n";
  }
  for (clit=app()->getCategories().begin();
       clit!=app()->getCategories().end();
       clit++) {
    AB_VALUE *v;

    v=AB_Value_new(0.0, 0);
    qs+=_handleRealCategory(dbProfile, parent, cdl, *clit, v, 0);
    AB_Value_free(v);
  }

  if (!showTrans) {
    qs+="</table>";
  }

  qs+="</html>";

  AB_Banking_Print(app()->getCInterface(),
                   KBanking::QStringToUtf8String(tr("Transaction Report)")).c_str(),
                   "REPORT:SIMPLEREPORT",
                   KBanking::QStringToUtf8String(shortDescription()).c_str(),
                   KBanking::QStringToUtf8String(qs).c_str());

  DBG_ERROR(0, "Printing report... done");

  GWEN_Time_free(minDate);
  GWEN_Time_free(maxDate);

  return true;
}




















Generated by  Doxygen 1.6.0   Back to index