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

timport.cpp

/***************************************************************************
 $RCSfile: timport.cpp,v $
                             -------------------
    cvs         : $Id: timport.cpp,v 1.25 2005/08/25 15:27:35 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 "app.h"
#include "timport.h"
#include "standingorder.h"

#include <gwenhywfar/debug.h>
#include <gwenhywfar/waitcallback.h>




TransactionImporter::DayData::DayData(int year, int month, int d)
:_year(year)
,_month(month)
,_day(d)
,_transactions(0){
  _transactions=new std::list<RefPointer<Transaction> >();


}


TransactionImporter::DayData::DayData(const TransactionImporter::DayData &d)
:_year(d._year)
,_month(d._month)
,_day(d._day)
,_transactions(0){
  _transactions=new std::list<RefPointer<Transaction> >();
}



TransactionImporter::DayData::~DayData(){
  DBG_DEBUG(0, "Deleting day");
  if (_transactions) {
    delete _transactions;
  }
}



void TransactionImporter::DayData::addTransaction(RefPointer<Transaction> t){
  assert(_transactions);
  _transactions->push_back(t);
}



void
TransactionImporter::DayData::replaceTransactions(std::list<RefPointer<Transaction> > *tl){
  delete _transactions;
  _transactions=tl;
}





TransactionImporter::AccountData::AccountData(Account *a)
:_account(a) {
}



TransactionImporter::AccountData::AccountData
(const TransactionImporter::AccountData &a)
:_account(a._account) {

}



TransactionImporter::AccountData::~AccountData(){
  std::list<DayData*>::iterator it;

  DBG_DEBUG(0, "Deleting AccountData");
  for (it=_newDayList.begin();
       it!=_newDayList.end();
       it++)
    delete *it;

}



const std::string &TransactionImporter::AccountData::accountNumber(){
  return _account->getAccountNumber();
}



const std::string &TransactionImporter::AccountData::bankCode(){
  return _account->getBankCode();
}



TransactionImporter::DayData*
TransactionImporter::AccountData::getNewDayData(int year,
                                                int month,
                                                int day){
  std::list<DayData*>::iterator it;

  for (it=_newDayList.begin(); it!=_newDayList.end(); it++) {
    if ((*it)->getYear()==year &&
        (*it)->getMonth()==month &&
        (*it)->getDay()==day)
      return *it;
  }
  _newDayList.push_back(new DayData(year, month, day));
  return _newDayList.back();
}








TransactionImporter::TransactionImporter(App *kb,
                               AB_IMEXPORTER_CONTEXT *ctx,
                                         GWEN_TYPE_UINT32 flags)
:_app(kb)
,_context(ctx)
,_flags(flags){




}



TransactionImporter::~TransactionImporter(){
  std::list<AccountData*>::iterator it;

  for (it=_accountDataList.begin();
       it!=_accountDataList.end();
       it++)
    delete *it;
}



Account*
TransactionImporter::askUserForAccount(const std::string &bankCode,
                                       const std::string &accountNumber){
  return 0;
}



GWEN_TIME *TransactionImporter::askUserForDate(const Transaction *t,
                                               const GWEN_TIME *ti){
  return 0;
}



Payee *TransactionImporter::askUserForPayee(RefPointer<Transaction> t,
                                            bool &aborted,
                                            bool &askNoMore){
  aborted=false;
  askNoMore=true;
  return 0;
}



TransactionImporter::DupeCheckResult
TransactionImporter::askUserForDuplicate(Account *a,
                                         RefPointer<Transaction> tnew,
                                         RefPointer<Transaction> told,
                                         const std::list<RefPointer<Transaction> > &dnl,
                                         const std::list<RefPointer<Transaction> > &dol,
                                         bool &askNoMore){
  return DupeCheck_Error;
}




bool TransactionImporter::_collapseSplits(AB_TRANSACTION *t,
                                          const std::string &bankCode,
                                          const std::string &accountId){
  int n;

  n=AB_Split_List_GetCount(AB_Transaction_GetSplits(t));
  if (n) {
    AB_SPLIT *sp;
    const char *s;

    if (n>2) {
      DBG_ERROR(0,
            "Transfer contains more than two splits, unable to handle");
      return false;
    }

    /* find split of this account */
    sp=AB_Split_List_First(AB_Transaction_GetSplits(t));
    while(sp) {
      const char *spBankCode;
      const char *spAccountId;

      spBankCode=AB_Split_GetBankCode(sp);
      spAccountId=AB_Split_GetAccountNumber(sp);
      if (spBankCode && spAccountId) {
      if (strcasecmp(spBankCode, bankCode.c_str())==0 &&
          strcasecmp(spAccountId, accountId.c_str())==0)
          /* split found */
        break;
      }
      sp=AB_Split_List_Next(sp);
    }
    if (sp) {
      /* read data from local split */
      AB_Transaction_SetLocalAccountNumber(t, AB_Split_GetAccountNumber(sp));
      AB_Transaction_SetLocalBankCode(t, AB_Split_GetBankCode(sp));
      s=GWEN_StringList_FirstString(AB_Split_GetName(sp));
      AB_Transaction_SetLocalName(t, s);
      AB_Transaction_SetValue(t, AB_Split_GetValue(sp));

      /* now get remote split */
      sp=AB_Split_List_Next(sp);
      if (!sp)
        sp=AB_Split_List_First(AB_Transaction_GetSplits(t));
    }
    else
      sp=AB_Split_List_First(AB_Transaction_GetSplits(t));

    /* read remote data */
    AB_Transaction_SetRemoteAccountNumber(t, AB_Split_GetAccountNumber(sp));
    AB_Transaction_SetRemoteBankCode(t, AB_Split_GetBankCode(sp));
    AB_Transaction_SetPurpose(t, AB_Split_GetPurpose(sp));
    AB_Transaction_SetRemoteName(t, AB_Split_GetName(sp));

    /* remove splits */
    AB_Split_List_Clear(AB_Transaction_GetSplits(t));
  }

  return true;
}



bool TransactionImporter::sortNewTransactions() {
  AB_IMEXPORTER_ACCOUNTINFO *ai;

  DBG_INFO(0, "Sorting transactions...");
  ai=AB_ImExporterContext_GetFirstAccountInfo(_context);
  if (!ai) {
    DBG_INFO(0, "No accounts");
  }
  while(ai) {
    AccountData *currentAccount;
    const AB_TRANSACTION *t;
    const GWEN_TIME *lastDate;
    DayData *currentDay;

    DBG_DEBUG(0, "Checking account (%s/%s)",
              AB_ImExporterAccountInfo_GetBankCode(ai),
              AB_ImExporterAccountInfo_GetAccountNumber(ai));
    currentAccount=
      getAccountData(AB_ImExporterAccountInfo_GetBankCode(ai),
                     AB_ImExporterAccountInfo_GetAccountNumber(ai));
    if (!currentAccount) {
      // TODO: ask user whether he wants to abort
      return false;
    }

    lastDate=0;
    currentDay=0;
    t=AB_ImExporterAccountInfo_GetFirstTransaction(ai);
    while(t) {
      Transaction *tr;
      const GWEN_TIME *ti;
      int d, month, year;

      tr=0;
      if (AB_Split_List_GetCount(AB_Transaction_GetSplits(t))) {
        AB_TRANSACTION *nt;

        nt=AB_Transaction_dup(t);
        if (!_collapseSplits(nt,
                             currentAccount->bankCode(),
                             currentAccount->accountNumber())) {
          DBG_ERROR(0, "Error collapsing splits of a transaction");
        }
        tr=new Transaction(nt);
        AB_Transaction_free(nt);
      }
      else
        tr=new Transaction(t);

      if (tr) {
        tr->gatherInfoFromPurpose();
        if (tr->getLocalBankCode().empty())
        tr->setLocalBankCode(currentAccount->bankCode());
      if (tr->getLocalAccountNumber().empty())
          tr->setLocalAccountNumber(currentAccount->accountNumber());

        ti=tr->getDate();
        if (!ti)
          ti=tr->getValutaDate();
        if (!ti)
          // still no date, ask the user about the date
          ti=askUserForDate(tr, lastDate);
        if (!ti) {
          DBG_ERROR(0, "No date, skip transaction");
          // TODO: Ask user for abort
        }
        else {
          lastDate=ti;
          if (GWEN_Time_GetBrokenDownUtcDate(ti, &d, &month, &year)) {
            DBG_ERROR(0, "Unable to break down date");
            // TODO: Ask user for abort
            return false;
          }
          else {
            // get corresponding day
            if (currentDay)
              if (currentDay->getDay()!=d ||
                  currentDay->getMonth()+1!=month ||
                  currentDay->getYear()!=year)
                currentDay=0;
            if (currentDay==0)
              currentDay=currentAccount->getNewDayData(year, month+1, d);
            assert(currentDay);
  
            // add transaction to that day
            currentDay->addTransaction(tr);
          }
        }
      }

      t=AB_ImExporterAccountInfo_GetNextTransaction(ai);
    } /* while */

    ai=AB_ImExporterContext_GetNextAccountInfo(_context);
  } /* while accounts */


  return true;
}







TransactionImporter::DupeCheckResult
TransactionImporter::checkForDuplicate(Account *a,
                                       RefPointer<Transaction> tnew,
                                       RefPointer<Transaction> told,
                                       std::list<RefPointer<Transaction> > &dnl,
                                       std::list<RefPointer<Transaction> > &dol,
                                       bool &dontAskAgain,
                                       TransactionImporter::DupeCheckResult lastRv){
  std::list<RefPointer<Transaction> >::iterator it;
  int newCount;
  int oldCount;

  /* count the occurrences of the new transaction in both the old and the
   * new list
   */
  DBG_DEBUG(0, "Equal, checking further");
  newCount=oldCount=0;

  if (_flags & TRANSACTION_IMPORTER_FLAGS_ASK_ALL_DUPES) {
    if (_flags & TRANSACTION_IMPORTER_FLAGS_FUZZY) {
      for (it=dol.begin(); it!=dol.end(); it++) {
        if ((*it).ref().matchFuzzy(tnew.ref(),
                                   _app->getSensitiveFuzzyThreshold())) {
        oldCount++;
      }
      }
    } // if fuzzy
    else {
      for (it=dol.begin(); it!=dol.end(); it++) {
      if (tnew.ref().getHash()==(*it).ref().getHash()) {
        oldCount++;
      }
      }
    } // if !fuzzy

    if (oldCount) {
      if (dontAskAgain)
      return lastRv;
      else
      return askUserForDuplicate(a, tnew, told, dnl, dol, dontAskAgain);
    }
    else {
      DBG_DEBUG(0, "Adding new");
      return DupeCheck_AddNew;
    }
  } // if askAllDupes
  else {
    for (it=dnl.begin(); it!=dnl.end(); it++) {
      if (tnew.ref().getHash()==(*it).ref().getHash())
      newCount++;
    }
    for (it=dol.begin(); it!=dol.end(); it++) {
      if (tnew.ref().getHash()==(*it).ref().getHash())
      oldCount++;
    }

    if (newCount>oldCount) {
      if (_flags & TRANSACTION_IMPORTER_FLAGS_COMPLETE_DAYS) {
      /* always complete days, and the new list contains more of these
       * exact same transactions, so simply add the new one
       */
      DBG_DEBUG(0, "Adding new");
      return DupeCheck_AddNew;
      }
      else {
      // not sure whether complete days are received, ask the user
      if (dontAskAgain) {
        DBG_DEBUG(0, "Returning previous value (%d)", lastRv);
        return lastRv;
      }
      else {
        DBG_DEBUG(0, "Asking user");
        return askUserForDuplicate(a, tnew, told, dnl, dol, dontAskAgain);
      }
      }
    }
    else {
      if (newCount<oldCount) {
      // the old list already contains more than the new one, don't add
      if (_flags & TRANSACTION_IMPORTER_FLAGS_COMPLETE_DAYS) {
        DBG_WARN(0, "Transactions missing in new list, should not happen");
      }
      }

      return DupeCheck_DismissNew;
    }
  }
}



bool TransactionImporter::_checkDay(Account *a,
                                    TransactionImporter::DayData *d,
                                    bool &askNoMore,
                                    TransactionImporter::DupeCheckResult &lastRv){
  std::list<RefPointer<Transaction> >::iterator it;

  if (!(_flags & TRANSACTION_IMPORTER_FLAGS_OVERWRITE_DAYS)) {
    AH_STORAGE *st;
    GWEN_TYPE_UINT32 hdl;
  
    st=a->getStorage();
    assert(st);

    DBG_DEBUG(0, "Opening day");
    hdl=AH_Storage_OpenDay(st, d->getYear(), d->getMonth(), d->getDay(), 1);
    if (hdl) {
      GWEN_DB_NODE *dbT;
      std::list<RefPointer<Transaction> > *toAdd;
      std::list<RefPointer<Transaction> > oldTransactions;

      toAdd=new std::list<RefPointer<Transaction> >();

      // there is data for this day, check it
      dbT=AH_Storage_GetFirstTransaction(st, hdl);
      while(dbT) {
        oldTransactions.push_back(new Transaction(dbT));
        dbT=AH_Storage_GetNextTransaction(st, hdl);
      } // while transactions

      // check for duplicates
      for (it=d->getTransactions()->begin();
           it!=d->getTransactions()->end();
           it++) {
        std::list<RefPointer<Transaction> >::iterator itOld;
      bool handled;

        DBG_VERBOUS(0, "checking transaction");
        handled=false;

      // find duplicates
      for (itOld=oldTransactions.begin();
           itOld!=oldTransactions.end();
           itOld++) {
        bool isEqual;

        if (_flags & TRANSACTION_IMPORTER_FLAGS_FUZZY) {
          DBG_VERBOUS(0, "Fuzzy matching");
            isEqual=(*it).ref().matchFuzzy((*itOld).ref(),
                                           _app->getSensitiveFuzzyThreshold());
        }
        else
          isEqual=((*it).ref().getHash()==(*itOld).ref().getHash());


        if (isEqual) {
          DupeCheckResult rv;

          // duplicate candidate
          rv=checkForDuplicate(a,
                         *it, *itOld,
                         *(d->getTransactions()),
                         oldTransactions,
                         askNoMore,
                         lastRv);
          lastRv=rv;
          if (rv==DupeCheck_Error) {
            DBG_ERROR(0, "User aborted");
            AH_Storage_AbandonDay(st, hdl);
            delete toAdd;
            return false;
          }
          else if (rv==DupeCheck_AddNew) {
            DBG_INFO(0, "Adding duplicate");
            toAdd->push_back(*it);
          }
          else if (rv==DupeCheck_DismissNew) {
            // dismiss new transaction
            DBG_INFO(0, "Dismissing duplicate");
          }
          else if (rv==DupeCheck_RemoveOld) {
            // dismissing old
            DBG_INFO(0, "Removing old transaction");
            oldTransactions.erase(itOld);
          }
          else if (rv==DupeCheck_ReplaceOld) {
            // replace old
            DBG_INFO(0, "Replacing old transaction");
            oldTransactions.erase(itOld);
            toAdd->push_back(*it);
          }

          handled=true;
          break;
        } // for old transactions
      }
      if (!handled)
        toAdd->push_back(*it);
      } // for new transactions

      // add old transactions to list
      for (it=oldTransactions.begin();
         it!=oldTransactions.end();
         it++)
      toAdd->push_back(*it);
      /* replace new data for this day, the new list only contains
       * transactions which can be safely written
       */
      d->replaceTransactions(toAdd);
      DBG_DEBUG(0, "Closing day");
      AH_Storage_CloseDay(st, hdl);
    } // if old data for this day exists
  } // if not in overwrite mode

  // make sure all transactions have a date or valuta date
  for (it=d->getTransactions()->begin();
       it!=d->getTransactions()->end();
       it++) {
    const GWEN_TIME *ti;
    GWEN_TYPE_UINT32 id;

    // assign unique id if there was none
    id=(*it).ref().getTransactionId();
    if (id==0) {
      DBG_DEBUG(0, "Setting new id");
      (*it).ref().setTransactionId(_app->getNextUniqueId());
    }
    else {
      DBG_DEBUG(0, "id is %08x", id);
    }

    ti=(*it).ref().getDate();
    if (!ti)
      ti=(*it).ref().getValutaDate();
    if (!ti) {
      GWEN_TIME *nti;

      DBG_DEBUG(0, "Setting new date");
      // set UTC date, 12 o'clock (in this case: UTC date==local date
      nti=GWEN_Time_new(d->getYear(), d->getMonth()-1, d->getDay(),
                        12, 0, 0, 1);
      assert(nti);
      (*it).ref().setDate(nti);
      GWEN_Time_free(nti);
    } // if no time
  } // for

  return true;
}





bool TransactionImporter::checkTransactions(){
  std::list<AccountData*>::iterator it;
  DupeCheckResult lastRv=DupeCheck_Error;
  bool askNoMore=false;

  if (!sortNewTransactions()) {
    DBG_INFO(0, "Error sorting transactions");
    return false;
  }

  for (it=_accountDataList.begin();
       it!=_accountDataList.end();
       it++) {
    std::list<DayData*>::iterator dit;

    for (dit=(*it)->getNewDayList().begin();
         dit!=(*it)->getNewDayList().end();
         dit++) {
      if (!_checkDay((*it)->account(), *dit, askNoMore, lastRv)) {
        DBG_INFO(0, "Error checking day");
        return false;
      }
    } // for days
  } // for accounts

  return true;
}



bool TransactionImporter::importTransactions(){
  std::list<AccountData*>::iterator it;
  int acnt;
  bool askUser;

  askUser=_app->optionAutoAskForPayee();

  acnt=0;
  for (it=_accountDataList.begin();
       it!=_accountDataList.end();
       it++) {
    std::list<DayData*>::iterator dit;
    AH_STORAGE *st;
    int cnt;

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

    GWEN_WaitCallback_Enter(TRANSACTION_IMPORTER_CB_ID);
    GWEN_WaitCallback_SetProgressTotal((*it)->getNewDayList().size());
    GWEN_WaitCallback_SetProgressPos(0);
    cnt=0;
    for (dit=(*it)->getNewDayList().begin();
         dit!=(*it)->getNewDayList().end();
         dit++) {
      GWEN_TYPE_UINT32 hdl;
      std::list<RefPointer<Transaction> >::iterator xit;
      GWEN_TIME *ti1;

      DBG_DEBUG(0, "Handling day");

      // TODO: save day
      hdl=AH_Storage_OpenDay(st,
                             (*dit)->getYear(),
                             (*dit)->getMonth(),
                             (*dit)->getDay(), 0);
      if (!hdl) {
      DBG_ERROR(0, "Error opening day");
        GWEN_WaitCallback_Leave();
        return false;
      }

      if (AH_Storage_ClearDay(st, hdl)) {
        DBG_ERROR(0, "Could not clear day");
        AH_Storage_AbandonDay(st, hdl);
        GWEN_WaitCallback_Leave();
        return false;
      }

      // get lastTransactionDate
      // set UTC date, 12 o'clock (in this case: UTC date==local date
      ti1=GWEN_Time_new((*dit)->getYear(),
                  (*dit)->getMonth()-1,
                  (*dit)->getDay(),
                        12, 0, 0, 1);

      // add transactions
      for (xit=(*dit)->getTransactions()->begin();
           xit!=(*dit)->getTransactions()->end();
           xit++) {
      GWEN_DB_NODE *dbT;
        const GWEN_TIME *ti2;

        DBG_DEBUG(0, "Handling transaction");

        if ((*xit).ref().getPayee().empty()) {
          Payee *payee=0;

          if (_app->optionAutoAssignPayee()) {
            payee=_app->findPayeeByTransactionMatch((*xit).ptr());
            if (!payee) {
              if (askUser) {
                bool aborted=false;
                bool askNoMore=false;

                payee=askUserForPayee((*xit), aborted, askNoMore);
                if (!payee && aborted) {
                  DBG_ERROR(0, "User aborted import");
                  AH_Storage_AbandonDay(st, hdl);
                  GWEN_Time_free(ti1);
                  GWEN_WaitCallback_Leave();
                  return false;
                }
                if (askNoMore)
                  askUser=false;
              }
            }
          }
          if (payee) {
            const AB_VALUE *v;

            DBG_DEBUG(0, "Assigning payee %s",
                      payee->name().c_str());
            (*xit).ref().setPayee(payee->id());
            v=(*xit).ref().getValue();
            if (v) {
              if (AB_Value_IsNegative(v)) {
                AB_VALUE *nv;

                nv=AB_Value_dup(v);
                AB_Value_Negate(nv);
                payee->addOutValue(nv);
                AB_Value_free(nv);
              }
              else
                payee->addInValue(v);
            }
          }
        }

        dbT=GWEN_DB_Group_new("transaction");
        if (!((*xit).ref().toDb(dbT))) {
          DBG_ERROR(0, "Error storing transaction to DB");
          AH_Storage_AbandonDay(st, hdl);
          GWEN_DB_Group_free(dbT);
        GWEN_Time_free(ti1);
        GWEN_WaitCallback_Leave();
          return false;
        }

        if (AH_Storage_AddTransaction(st, hdl, dbT)) {
          DBG_ERROR(0, "Error storing transaction for day");
          AH_Storage_AbandonDay(st, hdl);
          GWEN_DB_Group_free(dbT);
          GWEN_Time_free(ti1);
          GWEN_WaitCallback_Leave();
          return false;
        }

      ti2=(*it)->account()->getLastTransactionDate();
      if (ti2) {
        if (0) {
          GWEN_BUFFER *tbuf;

          tbuf=GWEN_Buffer_new(0, 32, 0, 1);
          GWEN_Time_toString(ti1, "YYYY/MM/DD", tbuf);
          DBG_ERROR(0, "Ti1: %s", GWEN_Buffer_GetStart(tbuf));
          GWEN_Buffer_Reset(tbuf);
          GWEN_Time_toString(ti2, "YYYY/MM/DD", tbuf);
          DBG_ERROR(0, "Ti2: %s", GWEN_Buffer_GetStart(tbuf));
          GWEN_Buffer_free(tbuf);
        }
        if (GWEN_Time_Diff(ti2, ti1)<0) {
          (*it)->account()->setLastTransactionDate(ti1);
        }
      }
      else {
        (*it)->account()->setLastTransactionDate(ti1);
      }

      GWEN_DB_Group_free(dbT);
      } // for transaction

      // close day
      DBG_DEBUG(0, "Closing day");
      if (AH_Storage_CloseDay(st, hdl)) {
        DBG_ERROR(0, "Error storing transaction for day");
        AH_Storage_AbandonDay(st, hdl);
      GWEN_Time_free(ti1);
        GWEN_WaitCallback_Leave();
        return false;
      }
      cnt++;
      GWEN_Time_free(ti1);
      GWEN_WaitCallbackProgress(cnt);
    } // for days
    GWEN_WaitCallback_Leave();
    _app->appInfoTransactionsChanged((*it)->account());

    acnt++;
    GWEN_WaitCallback_SetProgressPos(acnt);
  } // for accounts

  return true;
}



bool TransactionImporter::importAccounts(){
  AB_IMEXPORTER_ACCOUNTINFO *ai;

  ai=AB_ImExporterContext_GetFirstAccountInfo(_context);
  while(ai) {
    AB_ACCOUNT_STATUS *ast;
    AB_ACCOUNT_STATUS *best;
    Account *a;

    best=0;
    DBG_DEBUG(0, "Checking account (%s/%s)",
               AB_ImExporterAccountInfo_GetBankCode(ai),
               AB_ImExporterAccountInfo_GetAccountNumber(ai));
    a=_app->findAccount(AB_ImExporterAccountInfo_GetBankCode(ai),
                        AB_ImExporterAccountInfo_GetAccountNumber(ai));
    if (!a) {
      /* account not found, TODO: ask the user to add it */
    }
    else {
      ast=AB_ImExporterAccountInfo_GetFirstAccountStatus(ai);
      while(ast) {
        if (!best)
          best=ast;
        else {
          const GWEN_TIME *tiBest;
          const GWEN_TIME *ti;
  
          tiBest=AB_AccountStatus_GetTime(best);
          ti=AB_AccountStatus_GetTime(ast);
  
          if (!tiBest) {
            best=ast;
          }
          else {
            if (ti) {
              double d;
  
              /* we have two times, compare them */
              d=GWEN_Time_Diff(ti, tiBest);
              if (d>0)
                /* newer */
                best=ast;
            }
          }
        }
        ast=AB_ImExporterAccountInfo_GetNextAccountStatus(ai);
      } /* while */
    }
    if (best) {
      DBG_DEBUG(0, "Adding account status");
      a->setAccountStatus(best);
    }
    ai=AB_ImExporterContext_GetNextAccountInfo(_context);
  } /* while accounts */

  return true;
}



bool TransactionImporter::importStandingOrders(){
  AB_IMEXPORTER_ACCOUNTINFO *ai;

  ai=AB_ImExporterContext_GetFirstAccountInfo(_context);
  while(ai) {
    Account *a;

    a=_app->findAccount(AB_ImExporterAccountInfo_GetBankCode(ai),
                        AB_ImExporterAccountInfo_GetAccountNumber(ai));
    if (!a) {
      /* account not found, TODO: ask the user to add it */
    }
    else {
      const AB_TRANSACTION *t;

      t=AB_ImExporterAccountInfo_GetFirstStandingOrder(ai);
      while(t) {
        RefPointer<StandingOrder> sto;

      // TODO: search for existing standing order
        sto=new StandingOrder(t);
        assert(sto.isValid());
        a->addStandingOrder(sto);
        t=AB_ImExporterAccountInfo_GetNextStandingOrder(ai);
      }
    }
    ai=AB_ImExporterContext_GetNextAccountInfo(_context);
  } /* while accounts */

  return true;
}



bool TransactionImporter::importDatedTransfers(){
  AB_IMEXPORTER_ACCOUNTINFO *ai;

  ai=AB_ImExporterContext_GetFirstAccountInfo(_context);
  while(ai) {
    Account *a;

    a=_app->findAccount(AB_ImExporterAccountInfo_GetBankCode(ai),
                        AB_ImExporterAccountInfo_GetAccountNumber(ai));
    if (!a) {
      /* account not found, TODO: ask the user to add it */
      DBG_ERROR(0, "Account not found");
    }
    else {
      const AB_TRANSACTION *t;

      t=AB_ImExporterAccountInfo_GetFirstDatedTransfer(ai);
      while(t) {
      RefPointer<Transfer> sto;

      // TODO: search for existing standing order
      sto=new Transfer(t);
      assert(sto.isValid());
      a->addDatedTransfer(sto);
        t=AB_ImExporterAccountInfo_GetNextDatedTransfer(ai);
      }
    }
    ai=AB_ImExporterContext_GetNextAccountInfo(_context);
  } /* while accounts */

  return true;
}



bool TransactionImporter::importContext(){
  bool rv;

  rv=importTransactions();
  rv&=importAccounts();
  rv&=importStandingOrders();
  rv&=importDatedTransfers();
  return rv;
}



TransactionImporter::AccountData*
TransactionImporter::getAccountData(const char *s1,
                                    const char *s2) {
  std::list<AccountData*>::iterator it;
  std::string bankCode;
  std::string accountNumber;
  Account *a;

  DBG_DEBUG(0, "Checking for account \"%s/%s\"", s1, s2);

  if (s1)
    bankCode=s1;
  if (s2)
    accountNumber=s2;

  a=0;
  for (it=_accountDataList.begin();
       it!=_accountDataList.end();
       it++) {
    if ((*it)->bankCode()==bankCode &&
        (*it)->accountNumber()==accountNumber)
      return *it;
  } // for

  if (!bankCode.empty() && !accountNumber.empty())
    a=_app->findAccount(bankCode.c_str(), accountNumber.c_str());
  if (!a) {
    // TODO: check for aliases
    // TODO: ask the user for alias
    a=askUserForAccount(bankCode, accountNumber);
    if (!a) {
      DBG_NOTICE(0, "Account not found");
      GWEN_WaitCallback_Log(GWEN_LoggerLevelNotice, "User aborted");
      return 0;
    }

    for (it=_accountDataList.begin();
         it!=_accountDataList.end();
         it++) {
      if ((*it)->bankCode()==a->getBankCode() &&
          (*it)->accountNumber()==a->getAccountNumber())
        return *it;
    } // for
  }

  DBG_DEBUG(0, "Adding account data");
  _accountDataList.push_back(new AccountData(a));
  return _accountDataList.back();
}










Generated by  Doxygen 1.6.0   Back to index