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

assigncategories.cpp

/***************************************************************************
 $RCSfile: assigncategories.cpp,v $
                             -------------------
    cvs         : $Id: assigncategories.cpp,v 1.2 2005/08/31 05:24:20 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


#include "assigncategories.h"
#include "kbanking.h"
#include "selectcategory.h"

#include <qdatetime.h>
#include <qdatetimeedit.h>
#include <qmessagebox.h>
#include <qlineedit.h>
#include <qprogressdialog.h>
#include <qapplication.h>
#include <qpushbutton.h>

#include <gwenhywfar/debug.h>




AssignCategories::AssignCategories(KBanking *kb,
                                   QWidget* parent,
                                   const char* name,
                                   WFlags fl)
:CheckDuplicatesUI(0, name, fl)
,_app(kb)
,_aborted(false){

  setCaption(tr("Assign Categories"));
  QObject::connect((QObject*)abortButton, SIGNAL(clicked()),
                   this, SLOT(slotAbortClicked()));

  accountsProgress->setTotalSteps(-1);
  accountsProgress->setProgress(-1);
  transactionsProgress->setTotalSteps(-1);
  transactionsProgress->setProgress(-1);
}



AssignCategories::~AssignCategories(){
}



bool AssignCategories::assign() {
  std::list<Account*>::const_iterator it;
  int accnt;
  bool doneSomething=false;
  bool askNoMore=false;

  setCaption(tr("Assigning categories to transactions"));
  accountsProgress->setTotalSteps(_app->getAppAccounts().size());
  accountsProgress->setProgress(0);
  accnt=0;
  for (it=_app->getAppAccounts().begin();
       it!=_app->getAppAccounts().end();
       it++) {
    AH_STORAGE *st;
    int year, month, day;
    int rv;
    GWEN_IDLIST *idl;

    DBG_ERROR(0, "Handling account %s / %s",
              (*it)->getBankCode().c_str(),
              (*it)->getAccountNumber().c_str());

    st=(*it)->getStorage();
    assert(st);

    idl=AH_Storage_GetAvailableDays(st);
    assert(idl);
    rv=AH_Storage_GetFirstDay(st, idl, &year, &month, &day);
    if (!rv) {
      GWEN_TIME *ct;
      GWEN_TIME *ft;
      int totalDays;

      ct=GWEN_CurrentTime();
      assert(ct);
      ft=GWEN_Time_new(year, month-1, day, 0, 0, 0, 1);
      assert(ft);

      totalDays=(int)((GWEN_Time_Seconds(ct)-GWEN_Time_Seconds(ft))/
                      (60*60*24));
      transactionsProgress->setTotalSteps(totalDays);
      transactionsProgress->setProgress(0);
      GWEN_Time_free(ct);

      while(!rv) {
        GWEN_TYPE_UINT32 id = 0;
        GWEN_DB_NODE *db;
        std::list<RefPointer<Transaction> > tl;
        std::list<RefPointer<Transaction> >::iterator xait;
        GWEN_TIME *ti;

        ti=0;
        DBG_DEBUG(0, "Loading day %04d/%02d/%02d", year, month, day);
  
        qApp->processEvents();
        if (_aborted) {
          DBG_ERROR(0, "User aborted");
          if (id)
            AH_Storage_AbandonDay(st, id);
          GWEN_IdList_free(idl);
          return false;
        }
  
        id=AH_Storage_OpenDay(st, year, month, day, 0);
        if (!id) {
          DBG_ERROR(0, "Error loading day %04d/%02d/%02d",
                    year, month, day);
          GWEN_IdList_free(idl);
          return false;
        }
    
        db=AH_Storage_GetFirstTransaction(st, id);
        if (!db) {
          DBG_WARN(0, "No transactions in day %04d/%02d/%02d",
                   year, month, day);
        }
        while(db) {
          const char *cstr;

          DBG_DEBUG(0, "Got a transaction");
          cstr=GWEN_DB_GetCharValue(db, "category", 0, 0);
          if (!cstr || !*cstr) {
            Category *category;
            RefPointer<Transaction> t;
            bool aborted=false;
            bool automated=true;

            t=new Transaction();
            if (!t.ref().fromDb(db)) {
              DBG_ERROR(0, "Bad format of transaction in day %04d/%02d/%02d",
                        year, month, day);
              AH_Storage_AbandonDay(st, id);
              GWEN_IdList_free(idl);
              return false;
            }

            category=_app->findCategoryByTransactionMatch(t.ptr());
            if (!category && !askNoMore) {
              category=SelectCategory::assignCategory(_app, t.ptr(), aborted,
                                                      askNoMore,
                                                      this);
              automated=false;
            }
            if (category) {
              DBG_NOTICE(0, "Assigning category %s%s",
                         category->getId().c_str(),
                         automated?"(automatically)":"");
              GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS,
                                   "category",
                                   category->getId().c_str());
              doneSomething=true;
            }
            else {
              DBG_NOTICE(0, "Not assigning category");
              if (aborted) {
                DBG_ERROR(0, "Aborted");
                if (AH_Storage_CloseDay(st, id)) {
                  DBG_ERROR(0, "Error closing day %04d/%02d/%02d",
                            year, month, day);
                }
                if (doneSomething) {
                  _app->flagStaff()->categoriesUpdated();
                }
                GWEN_IdList_free(idl);
                return false;
              }
            }
          }
          else {
            DBG_DEBUG(0, "Transaction already has a category");
          }
          db=AH_Storage_GetNextTransaction(st, id);
        } // for transaction

        if (AH_Storage_CloseDay(st, id)) {
          DBG_ERROR(0, "Error closing day %04d/%02d/%02d",
                    year, month, day);
          if (doneSomething) {
            _app->flagStaff()->categoriesUpdated();
          }
          GWEN_IdList_free(idl);
          return false;
        }

        ti=GWEN_Time_new(year, month-1, day, 0, 0, 0, 1);
        (int)((GWEN_Time_Seconds(ct)-GWEN_Time_Seconds(ct))/
                      (60*60*24));
        transactionsProgress->setProgress((int)((GWEN_Time_Seconds(ti)-
                                                 GWEN_Time_Seconds(ft)
                                                )/
                                                (60*60*24)));
        GWEN_Time_free(ti);

        rv=AH_Storage_GetNextDay(st, idl, &year, &month, &day);
      } /* while !rv */
      GWEN_Time_free(ft);
    } /* if first day */
    GWEN_IdList_free(idl);

    accnt++;
    accountsProgress->setProgress(accnt);
  } // for account

  accountsProgress->setTotalSteps(1);
  accountsProgress->setProgress(1);
  transactionsProgress->setTotalSteps(1);
  transactionsProgress->setProgress(1);

  if (doneSomething) {
    _app->flagStaff()->categoriesUpdated();
  }
  return true;
}



bool AssignCategories::check() {
  std::list<Account*>::const_iterator it;
  int accnt;
  bool doneSomething=false;
  bool askNoMore=false;

  setCaption(tr("Checking categories of transactions"));
  accountsProgress->setTotalSteps(_app->getAppAccounts().size());
  accountsProgress->setProgress(0);
  accnt=0;
  for (it=_app->getAppAccounts().begin();
       it!=_app->getAppAccounts().end();
       it++) {
    AH_STORAGE *st;
    int year, month, day;
    int rv;
    GWEN_IDLIST *idl;

    DBG_ERROR(0, "Handling account %s / %s",
              (*it)->getBankCode().c_str(),
              (*it)->getAccountNumber().c_str());

    st=(*it)->getStorage();
    assert(st);

    idl=AH_Storage_GetAvailableDays(st);
    assert(idl);
    rv=AH_Storage_GetFirstDay(st, idl, &year, &month, &day);
    if (!rv) {
      GWEN_TIME *ct;
      GWEN_TIME *ft;
      int totalDays;

      ct=GWEN_CurrentTime();
      assert(ct);
      ft=GWEN_Time_new(year, month-1, day, 0, 0, 0, 1);
      assert(ft);

      totalDays=(int)((GWEN_Time_Seconds(ct)-GWEN_Time_Seconds(ft))/
                      (60*60*24));
      transactionsProgress->setTotalSteps(totalDays);
      transactionsProgress->setProgress(0);
      GWEN_Time_free(ct);

      while(!rv) {
        GWEN_TYPE_UINT32 id = 0;
        GWEN_DB_NODE *db;
        std::list<RefPointer<Transaction> > tl;
        std::list<RefPointer<Transaction> >::iterator xait;
        GWEN_TIME *ti;

        ti=0;
        DBG_DEBUG(0, "Loading day %04d/%02d/%02d", year, month, day);
  
        qApp->processEvents();
        if (_aborted) {
          DBG_ERROR(0, "User aborted");
          if (id)
            AH_Storage_AbandonDay(st, id);
          GWEN_IdList_free(idl);
          return false;
        }
  
        id=AH_Storage_OpenDay(st, year, month, day, 0);
        if (!id) {
          DBG_ERROR(0, "Error loading day %04d/%02d/%02d",
                    year, month, day);
          GWEN_IdList_free(idl);
          return false;
        }
    
        db=AH_Storage_GetFirstTransaction(st, id);
        if (!db) {
          DBG_WARN(0, "No transactions in day %04d/%02d/%02d",
                   year, month, day);
        }
        while(db) {
          const char *cstr;

          DBG_DEBUG(0, "Got a transaction");
          cstr=GWEN_DB_GetCharValue(db, "category", 0, 0);
          if (cstr) {
            Category *category;
            RefPointer<Transaction> t;
            bool aborted=false;
            bool automated=true;

            t=new Transaction();
            if (!t.ref().fromDb(db)) {
              DBG_ERROR(0, "Bad format of transaction in day %04d/%02d/%02d",
                        year, month, day);
              AH_Storage_AbandonDay(st, id);
              GWEN_IdList_free(idl);
              return false;
            }

            if (*cstr)
              category=_app->findCategoryById(cstr);
            else
              category=0;
            if (!category && !askNoMore) {
              category=SelectCategory::assignCategory(_app, t.ptr(), aborted,
                                                      askNoMore,
                                                      this);
              automated=false;
            }
            if (category) {
              DBG_NOTICE(0, "Assigning category %s%s",
                         category->getId().c_str(),
                         automated?"(automatically)":"");
              GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS,
                                   "category",
                                   category->getId().c_str());
              doneSomething=true;
            }
            else {
              DBG_NOTICE(0, "Not assigning category");
              if (aborted) {
                DBG_ERROR(0, "Aborted");
                if (AH_Storage_CloseDay(st, id)) {
                  DBG_ERROR(0, "Error closing day %04d/%02d/%02d",
                            year, month, day);
                }
                if (doneSomething) {
                  _app->flagStaff()->categoriesUpdated();
                }
                GWEN_IdList_free(idl);
                return false;
              }
            }
          }
          else {
            DBG_DEBUG(0, "Transaction has no category");
          }
          db=AH_Storage_GetNextTransaction(st, id);
        } // for transaction

        if (AH_Storage_CloseDay(st, id)) {
          DBG_ERROR(0, "Error closing day %04d/%02d/%02d",
                    year, month, day);
          if (doneSomething) {
            _app->flagStaff()->categoriesUpdated();
          }
          GWEN_IdList_free(idl);
          return false;
        }

        ti=GWEN_Time_new(year, month-1, day, 0, 0, 0, 1);
        (int)((GWEN_Time_Seconds(ct)-GWEN_Time_Seconds(ct))/
                      (60*60*24));
        transactionsProgress->setProgress((int)((GWEN_Time_Seconds(ti)-
                                                 GWEN_Time_Seconds(ft)
                                                )/
                                                (60*60*24)));
        GWEN_Time_free(ti);

        rv=AH_Storage_GetNextDay(st, idl, &year, &month, &day);
      } /* while !rv */
      GWEN_Time_free(ft);
    } /* if first day */
    GWEN_IdList_free(idl);

    accnt++;
    accountsProgress->setProgress(accnt);
  } // for account

  accountsProgress->setTotalSteps(1);
  accountsProgress->setProgress(1);
  transactionsProgress->setTotalSteps(1);
  transactionsProgress->setProgress(1);

  if (doneSomething) {
    _app->flagStaff()->categoriesUpdated();
  }
  return true;
}



void AssignCategories::slotAbortClicked(){
  _aborted=true;
  abortButton->setEnabled(false);
}






Generated by  Doxygen 1.6.0   Back to index