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; }
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; }