Ejemplo n.º 1
0
int AHB_DTAUS__CreateSetC(GWEN_BUFFER *dst,
                          GWEN_DB_NODE *cfg,
                          GWEN_DB_NODE *xa,
			  AB_VALUE *sumEUR,
                          AB_VALUE *sumDEM,
                          AB_VALUE *sumBankCodes,
                          AB_VALUE *sumAccountIds){
  unsigned int i;
  const char *p;
  char buffer[32];
  int isDebitNote;
  int isEuro;
  unsigned int extSets;
  //unsigned int startPos;
  AB_VALUE *val;
  GWEN_STRINGLIST *purposeList;

  DBG_DEBUG(AQBANKING_LOGDOMAIN, "Creating C set");

  /* ______________________________________________________________________
   * preparations
   */
  purposeList=GWEN_StringList_new();
  /* cut purpose lines into manageable portions (max 27 chars) */
  for (i=0; ; i++) {
    int slen;
    GWEN_BUFFER *nbuf;

    p=GWEN_DB_GetCharValue(xa, "purpose", i, 0);
    if (p==NULL)
      break;
    if (i>14) {
      DBG_ERROR(AQBANKING_LOGDOMAIN, "Too many purpose lines (maxmimum is 14)");
      GWEN_StringList_free(purposeList);
      return -1;
    }

    slen=strlen(p);
    nbuf=GWEN_Buffer_new(0, slen+1, 0, 1);
    AB_ImExporter_Utf8ToDta(p, -1, nbuf);
    p=GWEN_Buffer_GetStart(nbuf);

    while(*p) {
      while(*p>0 && *p<33)
	p++;
      slen=strlen(p);
      if (slen==0)
        break;
      else if (slen>27) {
	char *ns;

	ns=(char*) malloc(28);
	assert(ns);
	memmove(ns, p, 27);
	ns[27]=0;
	/* let stringlist take over ownership of the the string */
	GWEN_StringList_AppendString(purposeList, ns, 1, 0);
	p+=27;
      }
      else {
	GWEN_StringList_AppendString(purposeList, p, 0, 0);
	break;
      }
    }
    GWEN_Buffer_free(nbuf);
  } /* for */

  //startPos=GWEN_Buffer_GetPos(dst);
  GWEN_Buffer_AllocRoom(dst, 256);

  isDebitNote=(strcasecmp(GWEN_DB_GetCharValue(cfg, "type", 0, "transfer"),
                          "debitnote")==0);
  isEuro=(strcasecmp(GWEN_DB_GetCharValue(cfg, "currency", 0, "EUR"),
                     "EUR")==0);

  /* compute number of extension sets */
  extSets=0;

  /* add purpose */
  if (GWEN_StringList_Count(purposeList))
    extSets+=GWEN_StringList_Count(purposeList)-1;

  /* add name */
  for (i=1; i<2; i++) { /* max 1 extset for local name */
    if (GWEN_DB_GetCharValue(xa, "localName", i, 0)==0)
      break;
    if (i>1) {
      DBG_ERROR(AQBANKING_LOGDOMAIN, "Too many name lines (maxmimum is 2)");
      GWEN_StringList_free(purposeList);
      return -1;
    }
    extSets++;
  } /* for */

  /* add other name */
  for (i=1; i<2; i++) { /* max 1 extset for remote name */
    if (GWEN_DB_GetCharValue(xa, "remoteName", i, 0)==0)
      break;
    if (i>1) {
      DBG_ERROR(AQBANKING_LOGDOMAIN, "Too many peer name lines (maxmimum is 2)");
      GWEN_StringList_free(purposeList);
      return -1;
    }
    extSets++;
  } /* for */

  /* check number of extension sets */
  if (extSets>15) {
    DBG_ERROR(AQBANKING_LOGDOMAIN, "Too many extension sets (%d)", extSets);
    GWEN_StringList_free(purposeList);
    return -1;
  }

  /* ______________________________________________________________________
   * actually write C set
   */

  /* field 1, 2: record header */
  snprintf(buffer, sizeof(buffer), "%04d", 187+(extSets*29));
  GWEN_Buffer_AppendString(dst, buffer);
  GWEN_Buffer_AppendByte(dst, 'C');

  /* field 3: acting bank code */
  if (AHB_DTAUS__AddNum(dst, 8, GWEN_DB_GetCharValue(cfg, "bankCode", 0, ""))) {
    DBG_ERROR(AQBANKING_LOGDOMAIN, "Error writing to buffer");
    GWEN_StringList_free(purposeList);
    return -1;
  }

  /* field 4: destination bank code */
  p=GWEN_DB_GetCharValue(xa, "remoteBankCode", 0, 0);
  if (p) {
    val=AB_Value_fromString(p);
    if (val==NULL) {
      DBG_ERROR(AQBANKING_LOGDOMAIN, "Bad bank code");
      GWEN_StringList_free(purposeList);
      return -1;
    }
    AB_Value_AddValue(sumBankCodes, val);
    AB_Value_free(val);
    if (AHB_DTAUS__AddNum(dst, 8, p)) {
      DBG_ERROR(AQBANKING_LOGDOMAIN, "Error writing to buffer");
      GWEN_StringList_free(purposeList);
      return -1;
    }
  }
  else {
    DBG_ERROR(AQBANKING_LOGDOMAIN, "Peer bank code missing");
    GWEN_StringList_free(purposeList);
    return -1;
  }

  /* field 5: destination account id */
  p=GWEN_DB_GetCharValue(xa, "remoteAccountNumber", 0, 0);
  if (p) {
    val=AB_Value_fromString(p);
    if (val==NULL) {
      DBG_ERROR(AQBANKING_LOGDOMAIN, "Bad account id");
      GWEN_StringList_free(purposeList);
      return -1;
    }
    AB_Value_AddValue(sumAccountIds, val);
    AB_Value_free(val);
    if (AHB_DTAUS__AddNum(dst, 10, p)) {
      DBG_ERROR(AQBANKING_LOGDOMAIN, "Error writing to buffer");
      GWEN_StringList_free(purposeList);
      return -1;
    }
  }
  else {
    DBG_ERROR(AQBANKING_LOGDOMAIN, "Peer account id missing");
    GWEN_StringList_free(purposeList);
    return -1;
  }

  /* field 6: internal customer number (0s for now) */
  for (i=0; i<13; i++) GWEN_Buffer_AppendByte(dst, '0');

  /* field 7a: text key */
  snprintf(buffer, sizeof(buffer), "%02d", GWEN_DB_GetIntValue(xa, "textkey", 0, isDebitNote?5:51));
  if (AHB_DTAUS__AddNum(dst, 2, buffer)) {
    DBG_ERROR(AQBANKING_LOGDOMAIN, "Error writing to buffer");
    GWEN_StringList_free(purposeList);
    return -1;
  }

  /* field 7b: text key extension */
  snprintf(buffer, sizeof(buffer), "%03d", GWEN_DB_GetIntValue(xa, "textkeyext", 0, 0));
  if (AHB_DTAUS__AddNum(dst, 3, buffer)) {
    DBG_ERROR(AQBANKING_LOGDOMAIN, "Error writing to buffer");
    GWEN_StringList_free(purposeList);
    return -1;
  }

  /* field 8: bank internal field */
  GWEN_Buffer_AppendByte(dst, ' ');

  /* field 9: value in DEM */
  if (!isEuro) {
    val=AB_Value_fromString(GWEN_DB_GetCharValue(xa, "value/value", 0, "0,0"));
    if (val==NULL || AB_Value_IsZero(val)) {
      AB_Value_free(val);
      DBG_ERROR(AQBANKING_LOGDOMAIN, "Bad DEM value:");
      GWEN_StringList_free(purposeList);
      return -1;
    }
    AB_Value_AddValue(sumDEM, val);
    snprintf(buffer, sizeof(buffer), "%011.0f", AB_Value_GetValueAsDouble(val)*100.0);
    AB_Value_free(val);
    if (AHB_DTAUS__AddNum(dst, 11, buffer)) {
      DBG_ERROR(AQBANKING_LOGDOMAIN, "Error writing to buffer");
      GWEN_StringList_free(purposeList);
      return -1;
    }
  }
  else {
    if (AHB_DTAUS__AddNum(dst, 11, "0")) {
      DBG_ERROR(AQBANKING_LOGDOMAIN, "Error writing to buffer");
      GWEN_StringList_free(purposeList);
      return -1;
    }
  }

  /* field 10: local bank code */
  p=GWEN_DB_GetCharValue(xa, "localbankCode", 0, 0);
  if (!p)
    p=GWEN_DB_GetCharValue(cfg, "bankCode", 0, 0);
  if (!p) {
    DBG_ERROR(AQBANKING_LOGDOMAIN, "No local bank code");
    GWEN_StringList_free(purposeList);
    return -1;
  }
  if (AHB_DTAUS__AddNum(dst, 8, p)) {
    DBG_ERROR(AQBANKING_LOGDOMAIN, "Error writing to buffer");
    GWEN_StringList_free(purposeList);
    return -1;
  }

  /* field 11: local account id */
  p=GWEN_DB_GetCharValue(xa, "localAccountNumber", 0, 0);
  if (!p)
    GWEN_DB_GetCharValue(cfg, "accountId", 0, 0);
  if (!p) {
    DBG_ERROR(AQBANKING_LOGDOMAIN, "No local account number");
    GWEN_StringList_free(purposeList);
    return -1;
  }
  if (AHB_DTAUS__AddNum(dst, 10, p)) {
    DBG_ERROR(AQBANKING_LOGDOMAIN, "Error writing to buffer");
    GWEN_StringList_free(purposeList);
    return -1;
  }

  /* field 12: value in EUR */
  if (isEuro) {
    val=AB_Value_fromString(GWEN_DB_GetCharValue(xa, "value/value", 0, "0,0"));
    if (val==NULL || AB_Value_IsZero(val)) {
      AB_Value_free(val);
      DBG_ERROR(AQBANKING_LOGDOMAIN, "Bad EUR value:");
      GWEN_StringList_free(purposeList);
      return -1;
    }
    AB_Value_AddValue(sumEUR, val);
    snprintf(buffer, sizeof(buffer), "%011.0f", AB_Value_GetValueAsDouble(val)*100.0);
    AB_Value_free(val);
    if (AHB_DTAUS__AddNum(dst, 11, buffer)) {
      DBG_ERROR(AQBANKING_LOGDOMAIN, "Error writing to buffer");
      GWEN_StringList_free(purposeList);
      return -1;
    }
  }
  else {
    if (AHB_DTAUS__AddNum(dst, 11, "0")) {
      DBG_ERROR(AQBANKING_LOGDOMAIN, "Error writing to buffer");
      GWEN_StringList_free(purposeList);
      return -1;
    }
  }

  /* field 13: blanks */
  for (i=0; i<3; i++) GWEN_Buffer_AppendByte(dst, ' ');

  /* field 14a: peer name */
  if (AHB_DTAUS__AddWord(dst, 27, GWEN_DB_GetCharValue(xa, "remoteName", 0, ""))) {
    DBG_ERROR(AQBANKING_LOGDOMAIN, "Error writing to buffer");
    GWEN_StringList_free(purposeList);
    return -1;
  }

  /* field 14b: blanks */
  for (i=0; i<8; i++) GWEN_Buffer_AppendByte(dst, ' ');

  /* field 15: name */
  if (AHB_DTAUS__AddWord(dst, 27, GWEN_DB_GetCharValue(xa, "localname", 0, ""))) {
    DBG_ERROR(AQBANKING_LOGDOMAIN, "Error writing to buffer");
    GWEN_StringList_free(purposeList);
    return -1;
  }

  /* field 16: purpose */
  p=GWEN_StringList_FirstString(purposeList);
  if (p==NULL)
    p="";
  if (AHB_DTAUS__AddWord(dst, 27, p)) {
    DBG_ERROR(AQBANKING_LOGDOMAIN, "Error writing to buffer");
    GWEN_StringList_free(purposeList);
    return -1;
  }

  /* field 17a: currency */
  if (isEuro)
    GWEN_Buffer_AppendByte(dst, '1');
  else
    GWEN_Buffer_AppendByte(dst, ' ');

  /* field 17b: blanks */
  for (i=0; i<2; i++) GWEN_Buffer_AppendByte(dst, ' ');

  /* field 18: number of extension sets */
  snprintf(buffer, sizeof(buffer), "%02d", extSets);
  if (AHB_DTAUS__AddNum(dst, 2, buffer)) {
    DBG_ERROR(AQBANKING_LOGDOMAIN, "Error writing to buffer");
    GWEN_StringList_free(purposeList);
    return -1;
  }

  if (extSets) {
    unsigned int writtenExtSets=0;

    /* now append extension sets */

    /* add peer name lines */
    for (i=1; i<2; i++) { /* max: 1 extset */
      unsigned int j;

      p=GWEN_DB_GetCharValue(xa, "remoteName", i, 0);
      if (!p)
	break;

      /* append extension set */
      GWEN_Buffer_AppendString(dst, "01");
      if (AHB_DTAUS__AddWord(dst, 27, p)) {
	DBG_ERROR(AQBANKING_LOGDOMAIN, "Error writing to buffer");
	GWEN_StringList_free(purposeList);
	return -1;
      }
      writtenExtSets++;

      if (writtenExtSets==2)
	/* 2 ext sets written, so we need to align "C 2.Satzabschnitt" to 128 now */
	for (j=0; j<11; j++) GWEN_Buffer_AppendByte(dst, ' ');
      else if (writtenExtSets>2 && ((writtenExtSets-2) % 4)==0)
	/* "C 3-5.Satzabschnitt" complete, align to 128 bytes */
	for (j=0; j<12; j++) GWEN_Buffer_AppendByte(dst, ' ');
    } /* for */

    /* add purpose lines */
    for (i=1; i<GWEN_StringList_Count(purposeList); i++) {
      unsigned int j;

      p=GWEN_StringList_StringAt(purposeList, i);
      if (!p)
	break;

      /* append extension set */
      GWEN_Buffer_AppendString(dst, "02");
      /* strings in the list are already in DTA charset */
      if (AHB_DTAUS__AddDtaWord(dst, 27, p)) {
	DBG_ERROR(AQBANKING_LOGDOMAIN, "Error writing to buffer");
	GWEN_StringList_free(purposeList);
	return -1;
      }
      writtenExtSets++;

      if (writtenExtSets==2)
	/* 2 ext sets written, so we need to align "C 2.Satzabschnitt" to 128 now */
	for (j=0; j<11; j++) GWEN_Buffer_AppendByte(dst, ' ');
      else if (writtenExtSets>2 && ((writtenExtSets-2) % 4)==0)
	/* "C 3-5.Satzabschnitt" complete, align to 128 bytes */
	for (j=0; j<12; j++) GWEN_Buffer_AppendByte(dst, ' ');
    } /* for */

    /* add name lines */
    for (i=1; i<2; i++) { /* max: 1 extset */
      unsigned int j;

      p=GWEN_DB_GetCharValue(xa, "localname", i, 0);
      if (!p)
	break;

      /* append extension set */
      GWEN_Buffer_AppendString(dst, "03");
      if (AHB_DTAUS__AddWord(dst, 27, p)) {
	DBG_ERROR(AQBANKING_LOGDOMAIN, "Error writing to buffer");
	GWEN_StringList_free(purposeList);
	return -1;
      }
      writtenExtSets++;

      if (writtenExtSets==2)
	/* 2 ext sets written, so we need to align "C 2.Satzabschnitt" to 128 now */
	for (j=0; j<11; j++) GWEN_Buffer_AppendByte(dst, ' ');
      else if (writtenExtSets>2 && ((writtenExtSets-2) % 4)==0)
	/* "C 3-5.Satzabschnitt" complete, align to 128 bytes */
	for (j=0; j<12; j++) GWEN_Buffer_AppendByte(dst, ' ');
    } /* for */
  }

  i=((GWEN_Buffer_GetUsedBytes(dst)+127) & ~127)-GWEN_Buffer_GetUsedBytes(dst);
  while(i--)
    GWEN_Buffer_AppendByte(dst, ' ');

  GWEN_StringList_free(purposeList);
  return 0;
}
Ejemplo n.º 2
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;

}