Beispiel #1
0
int AH_ImExporterOFX_TransactionCallback_cb(const struct OfxTransactionData data,
                                            void *user_data)
{
  AH_IMEXPORTER_OFX *ieh;

  DBG_INFO(AQBANKING_LOGDOMAIN,
           "Transaction callback");
  ieh=(AH_IMEXPORTER_OFX *)user_data;

  if (!ieh->lastAccountInfo) {
    DBG_ERROR(AQBANKING_LOGDOMAIN, "Transaction but no account. Ignoring");
    return -1;
  }
  else {
    AB_TRANSACTION *t;

    t=AB_Transaction_new();
    if (data.account_id_valid)
      AB_Transaction_SetLocalAccountNumber(t, data.account_id);
    else
      AB_Transaction_SetLocalAccountNumber(t, "----");

    if (data.date_posted_valid) {
      GWEN_TIME *ti;

      ti=GWEN_Time_fromSeconds(data.date_posted);
      AB_Transaction_SetValutaDate(t, ti);
      GWEN_Time_free(ti);
    }

    if (data.date_initiated_valid) {
      GWEN_TIME *ti;

      ti=GWEN_Time_fromSeconds(data.date_initiated);
      AB_Transaction_SetDate(t, ti);
      GWEN_Time_free(ti);
    }

    if (data.fi_id_valid)
      AB_Transaction_SetFiId(t, data.fi_id);

    if (data.name_valid)
      AB_Transaction_AddRemoteName(t, data.name, 0);
    if (data.memo_valid)
      AB_Transaction_AddPurpose(t, data.memo, 0);

    if (data.amount_valid) {
      AB_VALUE *val;
      const char *cur;

      cur=0;
      if (data.account_ptr)
        if (data.account_ptr->currency_valid)
          cur=data.account_ptr->currency;
      val=AB_Value_fromDouble(data.amount);
      assert(val);
      AB_Value_SetCurrency(val, cur);
      if (data.invtransactiontype_valid)
        /* negate for investment transaction type (hack, see KMyMoney) */
        AB_Value_Negate(val);
      AB_Transaction_SetValue(t, val);
      AB_Value_free(val);
    }
    else {
      DBG_ERROR(AQBANKING_LOGDOMAIN,
                "No amount in transaction");
    }

    if (data.transactiontype_valid) {
      switch (data.transactiontype) {
      case OFX_CHECK:
        AB_Transaction_SetTransactionKey(t, "CHK");
        AB_Transaction_SetTransactionText(t, "Check");
        break;
      case OFX_INT:
        AB_Transaction_SetTransactionKey(t, "INT");
        AB_Transaction_SetTransactionText(t, "Interest");
        break;
      case OFX_DIV:
        AB_Transaction_SetTransactionKey(t, "DIV");
        AB_Transaction_SetTransactionText(t, "Dividend");
        break;
      case OFX_SRVCHG:
        AB_Transaction_SetTransactionKey(t, "CHG");
        AB_Transaction_SetTransactionText(t, "Service charge");
        break;
      case OFX_FEE:
        AB_Transaction_SetTransactionKey(t, "BRF");
        AB_Transaction_SetTransactionText(t, "Fee");
        break;
      case OFX_DEP:
        AB_Transaction_SetTransactionKey(t, "LDP"); /* FIXME: not sure */
        AB_Transaction_SetTransactionText(t, "Deposit");
        break;
      case OFX_ATM:
        AB_Transaction_SetTransactionKey(t, "MSC"); /* misc */
        AB_Transaction_SetTransactionText(t, "Cash dispenser");
        break;
      case OFX_POS:
        AB_Transaction_SetTransactionKey(t, "MSC"); /* misc */
        AB_Transaction_SetTransactionText(t, "Point of sale");
        break;
      case OFX_XFER:
        AB_Transaction_SetTransactionKey(t, "TRF");
        AB_Transaction_SetTransactionText(t, "Transfer");
        break;
      case OFX_PAYMENT:
        AB_Transaction_SetTransactionKey(t, "TRF"); /* FIXME: not sure */
        AB_Transaction_SetTransactionText(t, "Electronic payment");
        break;
      case OFX_CASH:
        AB_Transaction_SetTransactionKey(t, "MSC"); /* FIXME: not sure */
        AB_Transaction_SetTransactionText(t, "Cash");
        break;
      case OFX_DIRECTDEP:
        AB_Transaction_SetTransactionKey(t, "LDP"); /* FIXME: not sure */
        AB_Transaction_SetTransactionText(t, "Direct deposit");
        break;
      case OFX_DIRECTDEBIT:
        AB_Transaction_SetTransactionKey(t, "MSC"); /* FIXME: not sure */
        AB_Transaction_SetTransactionText(t, "Merchant initiated debit");
        break;
      case OFX_REPEATPMT:
        AB_Transaction_SetTransactionKey(t, "STO");
        AB_Transaction_SetTransactionText(t, "Standing order");
        break;
      case OFX_DEBIT:
      case OFX_CREDIT:
      case OFX_OTHER:
        AB_Transaction_SetTransactionKey(t, "MSC"); /* FIXME: not sure */
        break;
      }
    } /* if transaction type is valid */
    else if (data.invtransactiontype_valid) {
      switch (data.invtransactiontype) {
      case OFX_BUYDEBT:
      case OFX_BUYMF:
      case OFX_BUYOPT:
      case OFX_BUYOTHER:
      case OFX_BUYSTOCK:
        AB_Transaction_SetTransactionKey(t, "BUY");
        AB_Transaction_SetTransactionText(t, "Buy stocks or alike");
        AB_Transaction_SetSubType(t, AB_Transaction_SubTypeBuy);
        break;
      case OFX_REINVEST:
        AB_Transaction_SetTransactionKey(t, "REINV");
        AB_Transaction_SetTransactionText(t, "Reinvestment");
        AB_Transaction_SetSubType(t, AB_Transaction_SubTypeReinvest);
        break;
      case OFX_SELLDEBT:
      case OFX_SELLMF:
      case OFX_SELLOPT:
      case OFX_SELLOTHER:
      case OFX_SELLSTOCK:
        AB_Transaction_SetTransactionKey(t, "BUY");
        AB_Transaction_SetTransactionText(t, "Buy stocks or alike");
        AB_Transaction_SetSubType(t, AB_Transaction_SubTypeSell);
        break;
      case OFX_INCOME:
        AB_Transaction_SetTransactionKey(t, "DIV");
        AB_Transaction_SetTransactionText(t, "Dividend");
        AB_Transaction_SetSubType(t, AB_Transaction_SubTypeDividend);
        break;
      /* rest is unhandled */
      case OFX_CLOSUREOPT:
        AB_Transaction_SetTransactionText(t, "XCLOSUREOPT");
        break;
      case OFX_INVEXPENSE:
        AB_Transaction_SetTransactionText(t, "XINVEXPENSE");
        break;
      case OFX_JRNLFUND:
        AB_Transaction_SetTransactionText(t, "XJRNLFUND");
        break;
      case OFX_MARGININTEREST:
        AB_Transaction_SetTransactionText(t, "XMARGININTEREST");
        break;
      case OFX_RETOFCAP:
        AB_Transaction_SetTransactionText(t, "XRETOFCAP");
        break;
      case OFX_SPLIT:
        AB_Transaction_SetTransactionText(t, "XSPLIT");
        break;
      case OFX_TRANSFER:
        AB_Transaction_SetTransactionText(t, "XTRANSFER");
        break;
      default:
        break;
      }

#ifdef HAVE_OFX_0_8_PLUS
      if (data.fees_valid || data.commission_valid) {
        AB_VALUE *vFees;

        vFees=AB_Value_new();
        if (data.fees_valid) {
          AB_VALUE *v;

          v=AB_Value_fromDouble(data.fees);
          AB_Value_AddValue(vFees, v);
          AB_Value_free(v);
        }
        if (data.commission_valid) {
          AB_VALUE *v;

          v=AB_Value_fromDouble(data.commission);
          AB_Value_AddValue(vFees, v);
          AB_Value_free(v);
        }
        AB_Transaction_SetFees(t, vFees);
        AB_Value_free(vFees);
      }
#endif

      if (data.units_valid)
        AB_Transaction_SetUnits(t, data.units);
#ifdef HAVE_OFX_0_8_PLUS
      if (data.unitprice_valid && data.fees_valid) {
        AB_VALUE *v;

        v=AB_Value_fromDouble(data.fees); /* TODO: add currency */
        AB_Transaction_SetUnitPrice(t, v);
        AB_Value_free(v);
      }
#endif
    }
    else {
      DBG_NOTICE(AQBANKING_LOGDOMAIN, "No transaction type");
    }

    if (data.server_transaction_id_valid)
      AB_Transaction_SetBankReference(t, data.server_transaction_id);

    if (data.check_number_valid)
      AB_Transaction_SetCustomerReference(t, data.check_number);
    else if (data.reference_number_valid)
      AB_Transaction_SetCustomerReference(t, data.reference_number);

    DBG_INFO(0, "Adding transaction");
    AB_ImExporterAccountInfo_AddTransaction(ieh->lastAccountInfo, t);
  }

  return 0;

}
Beispiel #2
0
AB_TRANSACTION *mkSepaTransfer(AB_ACCOUNT *a, GWEN_DB_NODE *db, int expTransferType) {
  AB_BANKING *ab;
  AB_TRANSACTION *t;
  const char *s;
  int i;
  GWEN_TIME *d;

  assert(a);
  assert(db);

  ab=AB_Account_GetBanking(a);
  assert(ab);

  t=AB_Transaction_new();

  AB_Banking_FillGapsInTransaction(ab, a, t);

  s=GWEN_DB_GetCharValue(db, "name", 0, 0);
  if (s && *s)
    AB_Transaction_SetLocalName(t, s);

  /* remote account */
  s=GWEN_DB_GetCharValue(db, "remoteBankId", 0, 0);
  if (s && *s)
    AB_Transaction_SetRemoteBankCode(t, s);
  s=GWEN_DB_GetCharValue(db, "remoteAccountId", 0, 0);
  if (s && *s)
    AB_Transaction_SetRemoteAccountNumber(t, s);

  s=GWEN_DB_GetCharValue(db, "remoteIban", 0, 0);
  if (s && *s)
    AB_Transaction_SetRemoteIban(t, s);
  else {
    DBG_ERROR(0, "No remote IBAN given");
    AB_Transaction_free(t);
    return NULL;
  }

  s=GWEN_DB_GetCharValue(db, "remoteBic", 0, 0);
  if (s && *s)
    AB_Transaction_SetRemoteBic(t, s);
  else if (strncmp(AB_Transaction_GetLocalIban(t),
                   AB_Transaction_GetRemoteIban(t), 2)) {
    DBG_ERROR(0, "Remote BIC id required for international transaction");
    AB_Transaction_free(t);
    return NULL;
  }

  for (i=0; i<10; i++) {
    s=GWEN_DB_GetCharValue(db, "remoteName", i, 0);
    if (!s)
      break;
    if (*s)
      AB_Transaction_AddRemoteName(t, s, 0);
  }
  if (i<1) {
    DBG_ERROR(0, "No remote name given");
    AB_Transaction_free(t);
    return NULL;
  }

  /* transfer data */
  for (i=0; i<20; i++) {
    s=GWEN_DB_GetCharValue(db, "purpose", i, 0);
    if (!s)
      break;
    if (*s)
      AB_Transaction_AddPurpose(t, s, 0);
  }
  if (i<1) {
    DBG_ERROR(0, "No purpose given");
    AB_Transaction_free(t);
    return NULL;
  }

  i=GWEN_DB_GetIntValue(db, "textkey", 0, -1);
  if (i>0)
    AB_Transaction_SetTextKey(t, i);

  s=GWEN_DB_GetCharValue(db, "value", 0, 0);
  if (s && *s) {
    AB_VALUE *v;

    v=AB_Value_fromString(s);
    assert(v);
    if (AB_Value_IsNegative(v) || AB_Value_IsZero(v)) {
      DBG_ERROR(0, "Only positive non-zero amount allowed");
      AB_Transaction_free(t);
      return NULL;
    }
    AB_Transaction_SetValue(t, v);
    AB_Value_free(v);
  }
  else {
    DBG_ERROR(0, "No value given");
    AB_Transaction_free(t);
    return NULL;
  }

  /* dated transfer, SEPA debit notes */
  s=GWEN_DB_GetCharValue(db, "executionDate", 0, 0);
  if (s && *s) {
    GWEN_BUFFER *dbuf;

    dbuf=GWEN_Buffer_new(0, 32, 0, 1);
    GWEN_Buffer_AppendString(dbuf, s);
    GWEN_Buffer_AppendString(dbuf, "-00:00");
    d=GWEN_Time_fromUtcString(GWEN_Buffer_GetStart(dbuf),
                                     "YYYYMMDD-hh:mm");
    GWEN_Buffer_free(dbuf);
    if (d==0) {
      DBG_ERROR(0, "Invalid execution date value \"%s\"", s);
      AB_Transaction_free(t);
      return NULL;
    }
    AB_Transaction_SetDate(t, d);
    GWEN_Time_free(d);
  }

  /* standing orders */
  s=GWEN_DB_GetCharValue(db, "firstExecutionDate", 0, 0);
  if (s && *s) {
    GWEN_BUFFER *dbuf;

    dbuf=GWEN_Buffer_new(0, 32, 0, 1);
    GWEN_Buffer_AppendString(dbuf, s);
    GWEN_Buffer_AppendString(dbuf, "-00:00");
    d=GWEN_Time_fromUtcString(GWEN_Buffer_GetStart(dbuf),
                                     "YYYYMMDD-hh:mm");
    GWEN_Buffer_free(dbuf);
    if (d==0) {
      DBG_ERROR(0, "Invalid first execution date value \"%s\"", s);
      AB_Transaction_free(t);
      return NULL;
    }
    AB_Transaction_SetFirstExecutionDate(t, d);
    GWEN_Time_free(d);
  }

  s=GWEN_DB_GetCharValue(db, "lastExecutionDate", 0, 0);
  if (s && *s) {
    GWEN_BUFFER *dbuf;

    dbuf=GWEN_Buffer_new(0, 32, 0, 1);
    GWEN_Buffer_AppendString(dbuf, s);
    GWEN_Buffer_AppendString(dbuf, "-00:00");
    d=GWEN_Time_fromUtcString(GWEN_Buffer_GetStart(dbuf),
                                     "YYYYMMDD-hh:mm");
    GWEN_Buffer_free(dbuf);
    if (d==0) {
      DBG_ERROR(0, "Invalid last execution date value \"%s\"", s);
      AB_Transaction_free(t);
      return NULL;
    }
    AB_Transaction_SetLastExecutionDate(t, d);
    GWEN_Time_free(d);
  }

  if (expTransferType==AB_Job_TypeSepaCreateStandingOrder ||
      expTransferType==AB_Job_TypeSepaModifyStandingOrder) {
    const char *s;
    AB_TRANSACTION_PERIOD period=AB_Transaction_PeriodUnknown;

    /* only needed for standing orders */
    s=GWEN_DB_GetCharValue(db, "executionPeriod", 0, 0);
    if (s && *s) {
      period=AB_Transaction_Period_fromString(s);
      if (period==AB_Transaction_PeriodUnknown) {
        DBG_ERROR(0, "Invalid execution period value \"%s\"", s);
        AB_Transaction_free(t);
        return NULL;
      }
    }
    else {
      DBG_ERROR(0, "Missing execution period value");
      return NULL;
    }
    AB_Transaction_SetPeriod(t, period);

    i=GWEN_DB_GetIntValue(db, "executionCycle", 0, -1);
    if (i <= 0) {
      DBG_ERROR(0, "Invalid execution cycle value \"%d\"", i);
      AB_Transaction_free(t);
      return NULL;
    }
    AB_Transaction_SetCycle(t, i);

    i=GWEN_DB_GetIntValue(db, "executionDay", 0, -1);
    if (i <= 0 || (period == AB_Transaction_PeriodWeekly && i > 7) ||
        (period == AB_Transaction_PeriodMonthly && i > 30 &&
         (i < 97 || i > 99))) {
      DBG_ERROR(0, "Invalid execution day value \"%d\"", i);
      AB_Transaction_free(t);
      return NULL;
    }
    AB_Transaction_SetExecutionDay(t, i);
  }

  return t;
}
Beispiel #3
0
int AH_Job_GetTransactionsCreditCard_Process(AH_JOB *j, AB_IMEXPORTER_CONTEXT *ctx)
{
  AH_JOB_GETTRANSACTIONS *aj;
  AB_ACCOUNT *a;
  AB_IMEXPORTER_ACCOUNTINFO *ai;
  AB_USER *u;
  GWEN_DB_NODE *dbResponses;
  GWEN_DB_NODE *dbCurr;
  GWEN_BUFFER *tbooked;
  GWEN_BUFFER *tnoted;
  int rv;

  DBG_INFO(AQHBCI_LOGDOMAIN, "Processing JobGetTransactionsCreditCard");

  assert(j);
  aj=GWEN_INHERIT_GETDATA(AH_JOB, AH_JOB_GETTRANSACTIONS, j);
  assert(aj);

  tbooked=GWEN_Buffer_new(0, 1024, 0, 1);
  tnoted=GWEN_Buffer_new(0, 1024, 0, 1);

  dbResponses=AH_Job_GetResponses(j);
  assert(dbResponses);
  DBG_INFO(AQHBCI_LOGDOMAIN, "Response:");
  GWEN_DB_Dump(dbResponses, 2);
  DBG_INFO(AQHBCI_LOGDOMAIN, "Response end");


  a=AH_AccountJob_GetAccount(j);
  assert(a);
  ai=AB_ImExporterContext_GetOrAddAccountInfo(ctx,
                                              AB_Account_GetUniqueId(a),
                                              AB_Account_GetIban(a),
                                              AB_Account_GetBankCode(a),
                                              AB_Account_GetAccountNumber(a),
                                              AB_Account_GetAccountType(a));
  assert(ai);
  AB_ImExporterAccountInfo_SetAccountId(ai, AB_Account_GetUniqueId(a));

  u=AH_Job_GetUser(j);
  assert(u);

  /* search for "Transactions" */
  dbCurr=GWEN_DB_GetFirstGroup(dbResponses);
  while (dbCurr) {
    GWEN_DB_NODE *dbXA;

    rv=AH_Job_CheckEncryption(j, dbCurr);
    if (rv) {
      DBG_INFO(AQHBCI_LOGDOMAIN, "Compromised security (encryption)");
      GWEN_Buffer_free(tbooked);
      GWEN_Buffer_free(tnoted);
      AH_Job_SetStatus(j, AH_JobStatusError);
      return rv;
    }
    rv=AH_Job_CheckSignature(j, dbCurr);
    if (rv) {
      DBG_INFO(AQHBCI_LOGDOMAIN, "Compromised security (signature)");
      GWEN_Buffer_free(tbooked);
      GWEN_Buffer_free(tnoted);
      AH_Job_SetStatus(j, AH_JobStatusError);
      return rv;
    }

    dbXA=GWEN_DB_GetGroup(dbCurr, GWEN_PATH_FLAGS_NAMEMUSTEXIST,
                          "data/transactionscreditcard");
    if (dbXA) {
      GWEN_DB_NODE *dbT;
      GWEN_DB_NODE *dbV;
      GWEN_DATE *date;
      GWEN_DATE *valutaDate;
      const char *p;
      const char *ref;
      int i;

      dbT=GWEN_DB_GetGroup(dbXA, GWEN_PATH_FLAGS_NAMEMUSTEXIST,
                           "entries");
      while (dbT) {
        AB_VALUE *v1;
        AB_VALUE *v2;
        GWEN_STRINGLIST *purpose;
        AB_TRANSACTION *t;

        /* read date (Buchungsdatum) */
        p=GWEN_DB_GetCharValue(dbT, "date", 0, 0);
        if (p)
          date=GWEN_Date_fromStringWithTemplate(p, "YYYYMMDD");
        else
          date=NULL;

        /* read valutaData (Umsatzdatum) */
        p=GWEN_DB_GetCharValue(dbT, "valutaDate", 0, 0);
        if (p)
          valutaDate=GWEN_Date_fromStringWithTemplate(p, "YYYYMMDD");
        else
          valutaDate=NULL;

        /* read value */
        dbV=GWEN_DB_GetGroup(dbT, GWEN_PATH_FLAGS_NAMEMUSTEXIST,
                             "value");
        if (dbV)
          v1=AB_Value_fromDb(dbV);
        else
          v1=NULL;
        v2=0;
        if (!v1) {
          DBG_ERROR(AQHBCI_LOGDOMAIN, "Error parsing value from DB");
        }
        else {
          p=GWEN_DB_GetCharValue(dbT, "debitMark", 0, 0);
          if (p) {
            if (strcasecmp(p, "D")==0 ||
                strcasecmp(p, "RC")==0) {
              v2=AB_Value_dup(v1);
              AB_Value_Negate(v2);
            }
            else if (strcasecmp(p, "C")==0 ||
                     strcasecmp(p, "RD")==0)
              v2=AB_Value_dup(v1);
            else {
              DBG_ERROR(AQHBCI_LOGDOMAIN, "Bad debit mark \"%s\"", p);
              v2=0;
            }
          }
          AB_Value_free(v1);
        }

        /* read purpose */
        purpose=GWEN_StringList_new();
        for (i=0; i<10; i++) {
          p=GWEN_DB_GetCharValue(dbT, "purpose", i, 0);
          if (!p)
            break;
          GWEN_StringList_AppendString(purpose, p, 0, 0);
        }

        /* read reference */
        ref=GWEN_DB_GetCharValue(dbT, "reference", 0, 0);
        if (ref)
          GWEN_StringList_AppendString(purpose, ref, 0, 0);

        t=AB_Transaction_new();
        if (ref)
          AB_Transaction_SetFiId(t, ref);
        AB_Transaction_SetUniqueAccountId(t, AB_Account_GetUniqueId(a));
        AB_Transaction_SetLocalBankCode(t, AB_User_GetBankCode(u));
        AB_Transaction_SetLocalAccountNumber(t, AB_Account_GetAccountNumber(a));
        AB_Transaction_SetValutaDate(t, valutaDate);
        AB_Transaction_SetDate(t, date);
        AB_Transaction_SetValue(t, v2);
        AB_Transaction_SetPurposeFromStringList(t, purpose);
        DBG_INFO(AQHBCI_LOGDOMAIN, "Adding transaction");
        AB_ImExporterAccountInfo_AddTransaction(ai, t);

        GWEN_StringList_free(purpose);
        AB_Value_free(v2);
        GWEN_Date_free(date);
        GWEN_Date_free(valutaDate);

        dbT = GWEN_DB_FindNextGroup(dbT, "entries");
      } //while (dbT)
    } //if (dbXA)
    dbCurr=GWEN_DB_GetNextGroup(dbCurr);
  }

  return 0;
}