Project

General

Profile

Revision f4a16f5b

View differences:

.gitignore
112 112
src/libs/plugins/imexporters/q43/q43.xml
113 113
src/libs/plugins/parsers/dtaus/dtaus.xml
114 114
src/libs/plugins/parsers/swift/swift.xml
115
src/libs/plugins/imexporters/camt/camt.xml
115 116
src/test/abtest
116 117
src/test/test-dlg-setup
117 118
src/tools/aqbanking-cli/aqbanking-cli
configure.ac
487 487
)
488 488

  
489 489
if test "$aqbanking_imexporters" = "all"; then
490
  aqbanking_imexporters="csv eri2 ofx openhbci1 swift xmldb yellownet sepa ctxfile q43"
490
  aqbanking_imexporters="csv eri2 ofx openhbci1 swift xmldb yellownet sepa ctxfile q43 camt"
491 491
fi
492 492

  
493 493
for f in ${aqbanking_imexporters}; do
......
542 542
      aqbanking_plugins_imexporters_libs="$aqbanking_plugins_imexporters_libs q43/libabimexporters_q43.la"
543 543
      AC_DEFINE(AQBANKING_WITH_PLUGIN_IMEXPORTER_Q43, 1, [plugin availability])
544 544
      ;;
545
    camt)
546
      aqbanking_plugins_imexporters_dirs="$aqbanking_plugins_imexporters_dirs camt"
547
      aqbanking_plugins_imexporters_libs="$aqbanking_plugins_imexporters_libs camt/libabimexporters_camt.la"
548
      AC_DEFINE(AQBANKING_WITH_PLUGIN_IMEXPORTER_CAMT, 1, [plugin availability])
549
      ;;
545 550
    *)
546 551
      AC_MSG_ERROR("ERROR: Unknown plugin \"$f\"")
547 552
      ;;
......
1513 1518
  src/libs/plugins/imexporters/q43/q43.xml
1514 1519
  src/libs/plugins/imexporters/q43/profiles/Makefile
1515 1520
  src/libs/plugins/imexporters/q43/profiles/default.conf
1521
  src/libs/plugins/imexporters/camt/Makefile
1522
  src/libs/plugins/imexporters/camt/camt.xml
1523
  src/libs/plugins/imexporters/camt/profiles/Makefile
1524
  src/libs/plugins/imexporters/camt/profiles/default.conf
1525
  src/libs/plugins/imexporters/camt/profiles/052_001_02.conf
1516 1526
  src/libs/plugins/parsers/Makefile
1517 1527
  src/libs/plugins/parsers/swift/Makefile
1518 1528
  src/libs/plugins/parsers/swift/swift.xml
src/libs/aqbanking/banking_imex.c
51 51
# include "src/libs/plugins/imexporters/q43/q43.h"
52 52
#endif
53 53

  
54
#ifdef AQBANKING_WITH_PLUGIN_IMEXPORTER_CAMT
55
# include "src/libs/plugins/imexporters/camt/camt.h"
56
#endif
57

  
54 58

  
55 59

  
56 60
AB_IMEXPORTER *AB_Banking__CreateImExporterPlugin(AB_BANKING *ab, const char *modname){
......
104 108
    if (strcasecmp(modname, "q43")==0)
105 109
      return AB_ImExporterQ43_new(ab);
106 110
#endif
111

  
112
#ifdef AQBANKING_WITH_PLUGIN_IMEXPORTER_CAMT
113
    if (strcasecmp(modname, "camt")==0)
114
      return AB_ImExporterCAMT_new(ab);
115
#endif
116

  
107 117
    DBG_ERROR(AQBANKING_LOGDOMAIN, "Plugin [%s] not compiled-in", modname);
108 118
  }
109 119

  
src/libs/aqbanking/types2/Makefile.am
33 33
  ab_document.tm2 ab_document_list.tm2 ab_document_list2.tm2 \
34 34
  ab_message.tm2 ab_message_list.tm2 ab_message_list2.tm2 \
35 35
  ab_security.tm2 ab_security_list.tm2 ab_security_list2.tm2 \
36
  ab_balance.tm2 \
36
  ab_balance.tm2 ab_balance_list.tm2 \
37 37
  ab_account_status.tm2 ab_account_status_list.tm2 ab_account_status_list2.tm2 \
38 38
  ab_imexporter_accountinfo.tm2 ab_imexporter_accountinfo_list.tm2 ab_imexporter_accountinfo_list2.tm2 \
39 39
  ab_imexporter_context.tm2 ab_imexporter_context_list.tm2 ab_imexporter_context_list2.tm2 \
src/libs/aqbanking/types2/balance.xml
16 16
        with_db
17 17
        with_xml
18 18
        with_refcount
19
        with_list1
19 20
      </flags>
20 21
      
21 22
      <headers>
22 23
        <header type="sys" loc="pre">aqbanking/error.h</header>
23 24
        <header type="sys" loc="pre">gwenhywfar/types.h</header>
24
        <header type="sys" loc="pre">gwenhywfar/gwentime.h</header>
25
        <header type="sys" loc="pre">gwenhywfar/gwendate.h</header>
25 26

  
26 27
        <header type="sys" loc="post">aqbanking/value.h</header>
27 28
      </headers>
......
63 64
          </content>
64 65
        </inline>
65 66

  
67

  
68
        <inline loc="end" access="public">
69
          <typeFlagsMask>with_list1</typeFlagsMask>
70
          <typeFlagsValue>with_list1</typeFlagsValue>
71
          <content>
72
             $(api) AB_BALANCE *$(struct_prefix)_List_FindFirstByType(const $(struct_type)_LIST *bl, int ty);
73
          </content>
74
        </inline>
75

  
76
        <inline loc="code">
77
          <typeFlagsMask>with_list1</typeFlagsMask>
78
          <typeFlagsValue>with_list1</typeFlagsValue>
79
          <content>
80
             AB_BALANCE *$(struct_prefix)_List_FindFirstByType(const $(struct_type)_LIST *bl, int ty) {
81
               AB_BALANCE *bal;
82
               
83
               assert(bl);
84
               bal=AB_Balance_List_First(bl);
85
               while(bal) {
86
                 if (ty==AB_Balance_TypeNone || ty==bal->type)
87
                   return bal;
88
                 bal=AB_Balance_List_Next(bal);
89
               }
90
               
91
               return NULL;
92
             }
93
          </content>
94
        </inline>
95

  
96

  
97
        <inline loc="end" access="public">
98
          <typeFlagsMask>with_list1</typeFlagsMask>
99
          <typeFlagsValue>with_list1</typeFlagsValue>
100
          <content>
101
             $(api) AB_BALANCE *$(struct_prefix)_List_FindNextByType($(struct_type) *bal, int ty);
102
          </content>
103
        </inline>
104

  
105
        <inline loc="code">
106
          <typeFlagsMask>with_list1</typeFlagsMask>
107
          <typeFlagsValue>with_list1</typeFlagsValue>
108
          <content>
109
             AB_BALANCE *$(struct_prefix)_List_FindNextByType($(struct_type) *bal, int ty) {
110
               assert(bal);
111
               bal=AB_Balance_List_Next(bal);
112
               while(bal) {
113
                 if (ty==AB_Balance_TypeNone || ty==bal->type)
114
                   return bal;
115
                 bal=AB_Balance_List_Next(bal);
116
               }
117
               
118
               return NULL;
119
             }
120
          </content>
121
        </inline>
122

  
123

  
124
        <inline loc="end" access="public">
125
          <typeFlagsMask>with_list1</typeFlagsMask>
126
          <typeFlagsValue>with_list1</typeFlagsValue>
127
          <content>
128
             $(api) AB_BALANCE *$(struct_prefix)_List_GetLatestByType(const $(struct_type)_LIST *bl, int ty);
129
          </content>
130
        </inline>
131

  
132
        <inline loc="code">
133
          <typeFlagsMask>with_list1</typeFlagsMask>
134
          <typeFlagsValue>with_list1</typeFlagsValue>
135
          <content>
136
             AB_BALANCE *$(struct_prefix)_List_GetLatestByType(const $(struct_type)_LIST *bl, int ty) {
137
               AB_BALANCE *lastBal=NULL;
138
               const GWEN_DATE *lastDt=NULL;
139
               AB_BALANCE *bal=NULL;
140
             
141
               bal=AB_Balance_List_First(bl);
142
               while(bal) {
143
                 if (ty==0 || (AB_Balance_GetType(bal)==ty)) {
144
                   const GWEN_DATE *dt;
145
             
146
                   if (lastBal && lastDt && (dt=AB_Balance_GetDate(bal))) {
147
                     if (GWEN_Date_Compare(dt, lastDt)>0) {
148
                       lastBal=bal;
149
                       lastDt=dt;
150
                     }
151
                   }
152
                   else {
153
                     lastBal=bal;
154
                     lastDt=AB_Balance_GetDate(bal);
155
                   }
156
                 }
157
                 bal=AB_Balance_List_Next(bal);
158
               }
159

  
160
               return lastBal;
161
             }
162
          </content>
163
        </inline>
164

  
165

  
66 166
      </inlines>
67 167

  
68 168

  
......
70 170

  
71 171
    <enums>
72 172

  
173
      <enum id="AB_BALANCE_TYPE" prefix="AB_Balance_Type" type="AB_BALANCE_TYPE">
174
        <item name="none" value="0"/>
175
        <item name="noted"/>
176
        <item name="booked"/>
177
        <item name="bankLine"/>
178
        <item name="disposable"/>
179
        <item name="temporary"/>
180
      </enum>
181

  
73 182
    </enums>
74 183

  
75 184
    <defines>
......
79 188

  
80 189
    <members>
81 190

  
82
      <member name="time" type="gwen_time" maxlen="32" >
83
        <descr>
84
        </descr>
191
      <member name="date" type="gwen_date" maxlen="16" >
85 192
        <aqdb_type>AQDB_DataType_String</aqdb_type>
86 193
        <access>public</access>
87
        <flags>own</flags>
194
        <flags>own with_hash</flags>
88 195
        <setflags>const dup</setflags>
89 196
        <getflags>const</getflags>
90 197
        <default>NULL</default>
......
102 209
        <preset>NULL</preset>
103 210
      </member>
104 211

  
212
      <member name="type" type="int" maxlen="32" enum="AB_BALANCE_TYPE" >
213
        <default>AB_Balance_TypeUnknown</default>
214
        <preset>AB_Balance_TypeUnknown</preset>
215
        <access>public</access>
216
        <flags>enum with_getbymember</flags>
217
        <setflags>none</setflags>
218
        <getflags>none</getflags>
219
      </member>
220

  
105 221
    </members>
106 222

  
107 223
    
src/libs/aqbanking/types2/imexporter_accountinfo.xml
126 126
        </inline>
127 127

  
128 128

  
129

  
130 129
        <inline loc="end" access="public">
131 130
          <content>
132
             $(api) AB_ACCOUNT_STATUS *$(struct_prefix)_GetFirstAccountStatus(const $(struct_type) *as);
131
             $(api) AB_BALANCE *$(struct_prefix)_GetFirstBalance(const $(struct_type) *as);
133 132
          </content>
134 133
        </inline>
135 134

  
136 135
        <inline loc="code">
137 136
          <content>
138
             AB_ACCOUNT_STATUS *$(struct_prefix)_GetFirstAccountStatus(const $(struct_type) *as) {
139
               assert(as);
140
               if (as->accountStatusList)
141
                 return AB_AccountStatus_List_First(as->accountStatusList);
137
             AB_BALANCE *$(struct_prefix)_GetFirstBalance(const $(struct_type) *st) {
138
               assert(st);
139
               if (st->balanceList)
140
                 return AB_Balance_List_First(st->balanceList);
142 141
               return NULL;
143 142
             }
144 143
          </content>
145 144
        </inline>
146 145

  
147 146

  
148

  
149 147
        <inline loc="end" access="public">
150 148
          <content>
151
             $(api) void $(struct_prefix)_AddAccountStatus($(struct_type) *st, AB_ACCOUNT_STATUS *as);
149
             $(api) void $(struct_prefix)_AddBalance($(struct_type) *st, AB_BALANCE *bal);
152 150
          </content>
153 151
        </inline>
154 152

  
155 153
        <inline loc="code">
156 154
          <content>
157
             void $(struct_prefix)_AddAccountStatus($(struct_type) *st, AB_ACCOUNT_STATUS *as) {
158
               assert(as);
159
               if (NULL==st->accountStatusList)
160
                 st->accountStatusList=AB_AccountStatus_List_new();
161
               AB_AccountStatus_List_Add(as, st->accountStatusList);
155
             void $(struct_prefix)_AddBalance($(struct_type) *st, AB_BALANCE *bal) {
156
               assert(bal);
157
               if (NULL==st->balanceList)
158
                 st->balanceList=AB_Balance_List_new();
159
               AB_Balance_List_Add(bal, st->balanceList);
162 160
             }
163 161
          </content>
164 162
        </inline>
......
218 216
               assert(st);
219 217
               if (st->transactionList)
220 218
                 AB_Transaction_List_Clear(st->transactionList);
221
               if (st->accountStatusList)
222
                 AB_AccountStatus_List_Clear(st->accountStatusList);
219
               if (st->balanceList)
220
                 AB_Balance_List_Clear(st->balanceList);
223 221
               if (st->eStatementList)
224 222
                 AB_Document_List_Clear(st->eStatementList);
225 223
             }
......
934 932
        </descr>
935 933
      </member>
936 934

  
937
      <member name="accountStatusList" type="AB_ACCOUNT_STATUS_LIST" elementName="status">
935
      <member name="balanceList" type="AB_BALANCE_LIST" elementName="balance">
938 936
        <descr>
939 937
        </descr>
940 938
        <default>NULL</default>
941
        <preset>AB_AccountStatus_List_new()</preset>
939
        <preset>AB_Balance_List_new()</preset>
942 940
        <access>public</access>
943 941
        <flags>own</flags>
944 942
        <setflags>nodup</setflags>
src/libs/plugins/backends/aqhbci/ajobs/jobgetbalance.c
113 113

  
114 114
/* --------------------------------------------------------------- FUNCTION */
115 115
AB_BALANCE *AH_Job_GetBalance__ReadBalance(GWEN_DB_NODE *dbT) {
116
  GWEN_BUFFER *buf;
117
  GWEN_TIME *t;
118
  AB_VALUE *v1, *v2;
119
  AB_BALANCE *bal;
116
  AB_VALUE *v;
120 117
  const char *p;
118
  AB_BALANCE *bal;
119
  int isCredit=0;
121 120

  
122
  bal=0;
121
  bal=AB_Balance_new();
122

  
123
  /* get isCredit */
124
  p=GWEN_DB_GetCharValue(dbT, "debitMark", 0, 0);
125
  if (p) {
126
    if (strcasecmp(p, "D")==0 ||
127
	strcasecmp(p, "RC")==0) {
128
      isCredit=0;
129
    }
130
    else if (strcasecmp(p, "C")==0 ||
131
	     strcasecmp(p, "RD")==0)
132
      isCredit=1;
133
    else {
134
      DBG_ERROR(AQHBCI_LOGDOMAIN, "Bad debit mark \"%s\"", p);
135
      AB_Balance_free(bal);
136
      return NULL;
137
    }
138
  }
123 139

  
124
  /* read date and time */
125
  buf=GWEN_Buffer_new(0, 32, 0, 1);
140
  /* read date */
126 141
  p=GWEN_DB_GetCharValue(dbT, "date", 0, 0);
127
  if (p)
128
    GWEN_Buffer_AppendString(buf, p);
129
  else {
130
    AH_AccountJob_AddCurrentDate(buf);
142
  if (p) {
143
    GWEN_DATE *dt;
144

  
145
    dt=GWEN_Date_fromStringWithTemplate(p, "YYYYMMDD");
146
    if (dt) {
147
      AB_Balance_SetDate(bal, dt);
148
      GWEN_Date_free(dt);
149
    }
150
    else {
151
      DBG_ERROR(AQHBCI_LOGDOMAIN, "Bad date \"%s\"", p);
152
      AB_Balance_free(bal);
153
      return NULL;
154
    }
131 155
  }
132
  p=GWEN_DB_GetCharValue(dbT, "time", 0, 0);
133
  if (p)
134
    GWEN_Buffer_AppendString(buf, p);
135 156
  else {
136
    AH_AccountJob_AddCurrentTime(buf);
137
  }
138
  t=GWEN_Time_fromString(GWEN_Buffer_GetStart(buf), "YYYYMMDDhhmmss");
139
  if (!t) {
140
    DBG_ERROR(AQHBCI_LOGDOMAIN, "Error parsing date and time");
157
    GWEN_DATE *dt;
158

  
159
    DBG_WARN(AQHBCI_LOGDOMAIN, "No date, using current date");
160
    dt=GWEN_Date_CurrentDate();
161
    assert(dt);
162
    AB_Balance_SetDate(bal, dt);
163
    GWEN_Date_free(dt);
141 164
  }
142
  GWEN_Buffer_free(buf);
143 165

  
144
  /* read value */
145
  v1=AB_Value_fromDb(dbT);
146
  v2=0;
147
  if (!v1) {
166
  /* get value */
167
  v=AB_Value_fromDb(dbT);
168
  if (!v) {
148 169
    DBG_ERROR(AQHBCI_LOGDOMAIN, "Error parsing value from DB");
170
    AB_Balance_free(bal);
171
    return NULL;
149 172
  }
150 173
  else {
151
    p=GWEN_DB_GetCharValue(dbT, "debitMark", 0, 0);
152
    if (p) {
153
      if (strcasecmp(p, "D")==0 ||
154
	  strcasecmp(p, "RC")==0) {
155
	v2=AB_Value_dup(v1);
156
	AB_Value_Negate(v2);
157
      }
158
      else if (strcasecmp(p, "C")==0 ||
159
               strcasecmp(p, "RD")==0)
160
	v2=AB_Value_dup(v1);
161
      else {
162
	DBG_ERROR(AQHBCI_LOGDOMAIN, "Bad debit mark \"%s\"", p);
163
	v2=0;
164
      }
165
    }
166
    if (v2) {
167
      bal=AB_Balance_new();
168
      AB_Balance_SetTime(bal, t);
169
      AB_Balance_SetValue(bal, v2);
170
    }
171
    else
172
      bal=NULL;
173
  }
174
    if (!isCredit)
175
      AB_Value_Negate(v);
174 176

  
175
  AB_Value_free(v2);
176
  AB_Value_free(v1);
177
  GWEN_Time_free(t);
177
    AB_Balance_SetValue(bal, v);
178
    AB_Value_free(v);
179
  }
178 180

  
179 181
  return bal;
180 182
}
......
357 359
      return rv;
358 360
    }
359 361

  
360
    dbBalance=GWEN_DB_GetGroup(dbCurr, GWEN_PATH_FLAGS_NAMEMUSTEXIST,
361
                               "data/balance");
362
    dbBalance=GWEN_DB_GetGroup(dbCurr, GWEN_PATH_FLAGS_NAMEMUSTEXIST, "data/balance");
362 363
    if (!dbBalance)
363
      dbBalance=GWEN_DB_GetGroup(dbCurr, GWEN_PATH_FLAGS_NAMEMUSTEXIST,
364
                                         "data/balancecreditcard");
364
      dbBalance=GWEN_DB_GetGroup(dbCurr, GWEN_PATH_FLAGS_NAMEMUSTEXIST, "data/balancecreditcard");
365 365
    if (dbBalance) {
366
      AB_ACCOUNT_STATUS *acst;
367 366
      GWEN_DB_NODE *dbT;
368 367
      AB_ACCOUNT *a;
369 368
      AB_IMEXPORTER_ACCOUNTINFO *ai;
......
372 371
      if (GWEN_Logger_GetLevel(0)>=GWEN_LoggerLevel_Debug)
373 372
        GWEN_DB_Dump(dbBalance, 2);
374 373

  
375
      acst=AB_AccountStatus_new();
374
      a=AH_AccountJob_GetAccount(j);
375
      assert(a);
376
      ai=AB_ImExporterContext_GetOrAddAccountInfo(ctx,
377
						  AB_Account_GetUniqueId(a),
378
						  AB_Account_GetIban(a),
379
						  AB_Account_GetBankCode(a),
380
						  AB_Account_GetAccountNumber(a),
381
						  AB_Account_GetAccountType(a));
382
      assert(ai);
383

  
376 384

  
377 385
      /* read booked balance */
378
      dbT=GWEN_DB_GetGroup(dbBalance, GWEN_PATH_FLAGS_NAMEMUSTEXIST,
379
                           "booked");
386
      dbT=GWEN_DB_GetGroup(dbBalance, GWEN_PATH_FLAGS_NAMEMUSTEXIST, "booked");
380 387
      if (dbT) {
381 388
        AB_BALANCE *bal;
382 389

  
383 390
        bal=AH_Job_GetBalance__ReadBalance(dbT);
384 391
        if (bal) {
385
	  AB_AccountStatus_SetBookedBalance(acst, bal);
386
	  AB_AccountStatus_SetTime(acst, AB_Balance_GetTime(bal));
387
          AB_Balance_free(bal);
392
	  AB_Balance_SetType(bal, AB_Balance_TypeBooked);
393
	  AB_ImExporterAccountInfo_AddBalance(ai, bal);
388 394
        }
389 395
      }
390 396

  
391 397
      /* read noted balance */
392
      dbT=GWEN_DB_GetGroup(dbBalance, GWEN_PATH_FLAGS_NAMEMUSTEXIST,
393
                           "noted");
398
      dbT=GWEN_DB_GetGroup(dbBalance, GWEN_PATH_FLAGS_NAMEMUSTEXIST, "noted");
394 399
      if (dbT) {
395 400
        AB_BALANCE *bal;
396 401

  
397 402
        bal=AH_Job_GetBalance__ReadBalance(dbT);
398 403
        if (bal) {
399
	  AB_AccountStatus_SetNotedBalance(acst, bal);
400
	  if (AB_AccountStatus_GetTime(acst)==NULL)
401
	    AB_AccountStatus_SetTime(acst, AB_Balance_GetTime(bal));
402
          AB_Balance_free(bal);
403
        }
404
	  AB_Balance_SetType(bal, AB_Balance_TypeNoted);
405
	  AB_ImExporterAccountInfo_AddBalance(ai, bal);
406
	}
404 407
      }
405 408

  
409
#if 0
406 410
      /* read credit Line */
407
      dbT=GWEN_DB_GetGroup(dbBalance, GWEN_PATH_FLAGS_NAMEMUSTEXIST,
408
                           "creditLine");
411
      dbT=GWEN_DB_GetGroup(dbBalance, GWEN_PATH_FLAGS_NAMEMUSTEXIST, "creditLine");
409 412
      if (dbT) {
410 413
        AB_VALUE *v;
411 414

  
......
418 421
        }
419 422
        AB_Value_free(v);
420 423
      }
424
#endif
421 425

  
422
      a=AH_AccountJob_GetAccount(j);
423
      assert(a);
424
      ai=AB_ImExporterContext_GetOrAddAccountInfo(ctx,
425
                                                  AB_Account_GetUniqueId(a),
426
                                                  AB_Account_GetIban(a),
427
                                                  AB_Account_GetBankCode(a),
428
                                                  AB_Account_GetAccountNumber(a),
429
                                                  AB_Account_GetAccountType(a));
430
      assert(ai);
431

  
432
      /* add new account status */
433
      AB_ImExporterAccountInfo_AddAccountStatus(ai, acst);
434 426
      break; /* break loop, we found the balance */
435 427
    } /* if "Balance" */
436 428

  
src/libs/plugins/backends/aqhbci/ajobs/jobgettransactions.c
265 265
      dbT=GWEN_DB_FindFirstGroup(dbDay, "endSaldo");
266 266
      while (dbT) {
267 267
	GWEN_DB_NODE *dbX;
268
	GWEN_TIME *ti=0;
269
  
270
	dbX=GWEN_DB_GetGroup(dbT, GWEN_PATH_FLAGS_NAMEMUSTEXIST, "date");
271
	if (dbX)
272
	  ti=GWEN_Time_fromDb(dbX);
268
        const char *s;
269
	GWEN_DATE *dt=0;
270

  
271
        /* read date */
272
        s=GWEN_DB_GetCharValue(dbT, "date", 0, NULL);
273
        if (s && *s) {
274
          dt=GWEN_Date_fromString(s);
275
          if (dt==NULL) {
276
            DBG_ERROR(AQBANKING_LOGDOMAIN, "Bad date in saldo");
277
          }
278
        }
279

  
280
        /* read value */
273 281
	dbX=GWEN_DB_GetGroup(dbT, GWEN_PATH_FLAGS_NAMEMUSTEXIST, "value");
274 282
	if (dbX) {
275 283
	  AB_VALUE *v;
......
277 285
	  v=AB_Value_fromDb(dbX);
278 286
	  if (v) {
279 287
	    AB_BALANCE *bal;
280
	    AB_ACCOUNT_STATUS *as;
281 288
  
282 289
            bal=AB_Balance_new();
283
            AB_Balance_SetTime(bal, ti);
290
            AB_Balance_SetType(bal, AB_Balance_TypeNoted);
291
            AB_Balance_SetDate(bal, dt);
284 292
            AB_Balance_SetValue(bal, v);
285
	    AB_Value_free(v);
286
	    as=AB_AccountStatus_new();
287
	    if (ti)
288
	      AB_AccountStatus_SetTime(as, ti);
289
	    AB_AccountStatus_SetNotedBalance(as, bal);
290
	    AB_Balance_free(bal);
291
	    AB_ImExporterAccountInfo_AddAccountStatus(ai, as);
293
            AB_Value_free(v);
294
	    AB_ImExporterAccountInfo_AddBalance(ai, bal);
292 295
	  }
293 296
	}
294
	GWEN_Time_free(ti);
297
        GWEN_Date_free(dt);
295 298
  
296 299
	dbT=GWEN_DB_FindNextGroup(dbT, "endSaldo");
297 300
      } /* while */
src/libs/plugins/backends/aqpaypal/provider_getbalance.c
227 227
  /* now get the transactions */
228 228
  dbCurr=GWEN_DB_GetFirstGroup(dbResponse);
229 229
  while(dbCurr) {
230
    AB_ACCOUNT_STATUS *acst;
231 230
    AB_BALANCE *bal;
232
    GWEN_TIME *t=NULL;
231
    GWEN_DATE *t=NULL;
233 232
    AB_VALUE *vc;
234 233
    const char *p;
235 234
    
236 235
    DBG_NOTICE(AQPAYPAL_LOGDOMAIN, "Got a balance");
237 236
    
238
    acst=AB_AccountStatus_new();
239
    
240 237
    /* read and parse value */
241 238
    p=GWEN_DB_GetCharValue(dbCurr, "L_AMT", 0, 0);
242 239
    if (!p)
......
252 249
    
253 250
    p=GWEN_DB_GetCharValue(dbResponse, "TIMESTAMP", 0, NULL);
254 251
    if (p && *p) {
255
      t=GWEN_Time_fromUtcString(p, "YYYY-MM-DDThh:mm:ssZ");
252
      /*t=GWEN_Time_fromUtcString(p, "YYYY-MM-DDThh:mm:ssZ");*/
253
      t=GWEN_Date_fromStringWithTemplate(p, "YYYY-MM-DD");
254
      if (t==NULL) {
255
        DBG_ERROR(AQPAYPAL_LOGDOMAIN, "Invalid timespec [%s]", p);
256
      }
256 257
    }
257 258
    else {
258
      DBG_ERROR(AQPAYPAL_LOGDOMAIN, "Invalid timespec [%s]", p);
259
      DBG_ERROR(AQPAYPAL_LOGDOMAIN, "Missing timespec");
259 260
    }
260
    
261

  
261 262
    bal=AB_Balance_new();
262
    AB_Balance_SetTime(bal, t);
263
    AB_Balance_SetType(bal, AB_Balance_TypeBooked);
264
    AB_Balance_SetDate(bal, t);
263 265
    AB_Balance_SetValue(bal, vc);
264
    
266

  
265 267
    AB_Value_free(vc);
266
    GWEN_Time_free(t);
267
    
268
    AB_AccountStatus_SetBookedBalance(acst, bal);
269
    AB_AccountStatus_SetTime(acst, AB_Balance_GetTime(bal));
270
    AB_Balance_free(bal);
268
    GWEN_Date_free(t);
271 269
    
272
    /* add new account status */
273
    AB_ImExporterAccountInfo_AddAccountStatus(ai, acst);
270
    /* add new balance */
271
    AB_ImExporterAccountInfo_AddBalance(ai, bal);
274 272
    break; /* break loop, we found the balance */
275 273

  
276 274
    dbCurr=GWEN_DB_GetNextGroup(dbCurr);
src/libs/plugins/imexporters/Makefile.am
1 1
SUBDIRS=$(aqbanking_plugins_imexporters_dirs)
2
DIST_SUBDIRS=qif ofx swift csv openhbci1 eri2 yellownet xmldb sepa ctxfile q43
2
DIST_SUBDIRS=qif ofx swift csv openhbci1 eri2 yellownet xmldb sepa ctxfile q43 camt
3 3

  
4 4

  
5 5
noinst_LTLIBRARIES=libabimexporters.la
src/libs/plugins/imexporters/camt/Makefile.am
1
SUBDIRS=profiles
2

  
3
INCLUDES = -I$(top_srcdir)/src/libs/aqbanking -I$(aqbanking_symlinkdir) $(all_includes)
4

  
5
AM_CFLAGS=@visibility_cflags@
6

  
7
#extra_sources=
8

  
9

  
10
EXTRA_DIST=README $(extra_sources)
11

  
12
noinst_HEADERS=camt_p.h camt.h
13

  
14
imexporterplugindir = $(aqbanking_plugindir)/imexporters
15
noinst_LTLIBRARIES=libabimexporters_camt.la
16
imexporterplugin_DATA=camt.xml
17

  
18
libabimexporters_camt_la_SOURCES=camt.c
19

  
20

  
21
sources:
22
	for f in $(libabimexporters_camt_la_SOURCES); do \
23
	  echo $(subdir)/$$f >>$(top_srcdir)/i18nsources; \
24
	done
25
	for f in $(imexporterplugin_DATA); do \
26
	  echo $(subdir)/$$f >>$(top_srcdir)/pdsources; \
27
	done
28

  
29

  
30
cppcheck:
31
	for f in $(libabimexporters_camt_la_SOURCES); do \
32
	  cppcheck --force $$f ; \
33
	done
34

  
src/libs/plugins/imexporters/camt/camt.c
1
/***************************************************************************
2
    begin       : Sat Dec 15 2018
3
    copyright   : (C) 2018 by Martin Preuss
4
    email       : martin@libchipcard.de
5

  
6
 ***************************************************************************
7
 *          Please see toplevel file COPYING for license details           *
8
 ***************************************************************************/
9

  
10
#ifdef HAVE_CONFIG_H
11
# include <config.h>
12
#endif
13

  
14

  
15
#include "camt_p.h"
16

  
17

  
18
#include "i18n_l.h"
19
#include <aqbanking/banking.h>
20
#include <gwenhywfar/debug.h>
21
#include <gwenhywfar/misc.h>
22
#include <gwenhywfar/gui.h>
23
#include <gwenhywfar/inherit.h>
24
#include <gwenhywfar/gwendate.h>
25
#include <gwenhywfar/gwentime.h>
26
#include <gwenhywfar/text.h>
27

  
28
#include <ctype.h>
29

  
30

  
31

  
32

  
33
GWEN_INHERIT(AB_IMEXPORTER, AH_IMEXPORTER_CAMT);
34

  
35

  
36

  
37
AB_IMEXPORTER *AB_ImExporterCAMT_new(AB_BANKING *ab){
38
  AB_IMEXPORTER *ie;
39
  AH_IMEXPORTER_CAMT *ieh;
40

  
41
  ie=AB_ImExporter_new(ab, "camt");
42
  GWEN_NEW_OBJECT(AH_IMEXPORTER_CAMT, ieh);
43
  GWEN_INHERIT_SETDATA(AB_IMEXPORTER, AH_IMEXPORTER_CAMT, ie, ieh, AH_ImExporterCAMT_FreeData);
44

  
45
  AB_ImExporter_SetImportFn(ie, AH_ImExporterCAMT_Import);
46
  AB_ImExporter_SetExportFn(ie, AH_ImExporterCAMT_Export);
47
  AB_ImExporter_SetCheckFileFn(ie, AH_ImExporterCAMT_CheckFile);
48
  return ie;
49
}
50

  
51

  
52

  
53
void GWENHYWFAR_CB AH_ImExporterCAMT_FreeData(void *bp, void *p){
54
  AH_IMEXPORTER_CAMT *ieh;
55

  
56
  ieh=(AH_IMEXPORTER_CAMT*)p;
57
  GWEN_FREE_OBJECT(ieh);
58
}
59

  
60

  
61

  
62
int AH_ImExporterCAMT_Import(AB_IMEXPORTER *ie,
63
                             AB_IMEXPORTER_CONTEXT *ctx,
64
                             GWEN_SYNCIO *sio,
65
			     GWEN_DB_NODE *params) {
66
  int rv;
67
  GWEN_XMLNODE *xmlRoot;
68
  GWEN_XMLNODE *n;
69
  GWEN_XML_CONTEXT *xmlCtx;
70
  const char *camVersionWanted;
71

  
72
  /* read whole document into XML tree */
73
  xmlRoot=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, "camt52");
74
  xmlCtx=GWEN_XmlCtxStore_new(xmlRoot, GWEN_XML_FLAGS_DEFAULT);
75
  rv=GWEN_XMLContext_ReadFromIo(xmlCtx, sio);
76
  if (rv<0) {
77
    GWEN_XmlCtx_free(xmlCtx);
78
    GWEN_XMLNode_free(xmlRoot);
79
    return rv;
80
  }
81
  GWEN_XmlCtx_free(xmlCtx);
82

  
83
  n=GWEN_XMLNode_FindFirstTag(xmlRoot, "Document", NULL, NULL);
84
  if (n==NULL) {
85
    DBG_ERROR(AQBANKING_LOGDOMAIN, "<Document> element not found");
86
    GWEN_XMLNode_free(xmlRoot);
87
    return GWEN_ERROR_BAD_DATA;
88
  }
89

  
90
  /* debug */
91
  GWEN_XMLNode_Dump(n, 2);
92

  
93
  /* check document type */
94
  camVersionWanted=GWEN_DB_GetCharValue(params, "type", 0, "052.001.02");
95
  assert(camVersionWanted);
96

  
97
  if (strcasecmp(camVersionWanted, "052.001.02")==0)
98
    rv=AH_ImExporterCAMT_Import_052_001_02(ie, ctx, params, n);
99
  else
100
    rv=0;
101

  
102
  GWEN_XMLNode_free(xmlRoot);
103
  return rv;
104
}
105

  
106

  
107

  
108
int AH_ImExporterCAMT_Export(AB_IMEXPORTER *ie,
109
                             AB_IMEXPORTER_CONTEXT *ctx,
110
                             GWEN_SYNCIO *sio,
111
                             GWEN_DB_NODE *params) {
112
  return GWEN_ERROR_NOT_SUPPORTED;
113
}
114

  
115

  
116

  
117
int AH_ImExporterCAMT_CheckFile(AB_IMEXPORTER *ie, const char *fname) {
118
  return 0;
119
}
120

  
121

  
122

  
123

  
124
#include "camt52_001_02.c"
125

  
126

  
127

  
128

  
src/libs/plugins/imexporters/camt/camt.h
1
/***************************************************************************
2
    begin       : Sat Dec 15 2018
3
    copyright   : (C) 2018 by Martin Preuss
4
    email       : martin@libchipcard.de
5

  
6
 ***************************************************************************
7
 *          Please see toplevel file COPYING for license details           *
8
 ***************************************************************************/
9

  
10

  
11
#ifndef AQBANKING_IMEX_CAMT_H
12
#define AQBANKING_IMEX_CAMT_H
13

  
14

  
15
#include <aqbanking/imexporter.h>
16

  
17

  
18
AB_IMEXPORTER *AB_ImExporterCAMT_new(AB_BANKING *ab);
19

  
20

  
21
#endif /* AQBANKING_IMEX_CAMT_H */
src/libs/plugins/imexporters/camt/camt.xml.in
1
<plugin name="camt" type="imexporter" import="1" export="1" i18n="aqbanking" >
2
  <version>@AQBANKING_VERSION_STRING@</version>
3
  <author>Martin Preuss(martin@libchipcard.de)</author>
4
  <short>This plugin reads and writes CAMT files.</short>
5
  <descr>
6
    This plugin imports CAMT files.
7
  </descr>
8
</plugin>
9

  
src/libs/plugins/imexporters/camt/camt52_001_02.c
1
/***************************************************************************
2
    begin       : Sat Dec 15 2018
3
    copyright   : (C) 2018 by Martin Preuss
4
    email       : martin@libchipcard.de
5

  
6
 ***************************************************************************
7
 *          Please see toplevel file COPYING for license details           *
8
 ***************************************************************************/
9

  
10

  
11

  
12

  
13
static void _import_052_001_02_read_account_spec(AB_IMEXPORTER *ie,
14
                                                 GWEN_XMLNODE *xmlNode,
15
                                                 AB_ACCOUNT_SPEC *accountSpec) {
16
  const char *s;
17

  
18
  s=GWEN_XMLNode_GetCharValueByPath(xmlNode, "Id/IBAN", NULL);
19
  if (s && *s)
20
    AB_AccountSpec_SetIban(accountSpec, s);
21

  
22
  s=GWEN_XMLNode_GetCharValueByPath(xmlNode, "Ccy", NULL);
23
  if (s && *s)
24
    AB_AccountSpec_SetCurrency(accountSpec, s);
25

  
26
  s=GWEN_XMLNode_GetCharValueByPath(xmlNode, "Ownr/Nm", NULL);
27
  if (s && *s)
28
    AB_AccountSpec_SetOwnerName(accountSpec, s);
29

  
30
  s=GWEN_XMLNode_GetCharValueByPath(xmlNode, "Svcr/FinInstnId/BIC", NULL);
31
  if (s && *s)
32
    AB_AccountSpec_SetBic(accountSpec, s);
33

  
34
}
35

  
36

  
37

  
38
static int _import_052_001_02_read_balance(AB_IMEXPORTER *ie,
39
                                           GWEN_XMLNODE *xmlNode,
40
                                           AB_IMEXPORTER_ACCOUNTINFO *accountInfo) {
41
  const char *s;
42
  GWEN_XMLNODE *n;
43
  AB_BALANCE *balance=NULL;
44

  
45
  balance=AB_Balance_new();
46

  
47
  /* read amount */
48
  n=GWEN_XMLNode_GetNodeByXPath(xmlNode, "Amt", GWEN_PATH_FLAGS_NAMEMUSTEXIST);
49
  if (n) {
50
    const char *currency;
51
    AB_VALUE *val=NULL;
52

  
53
    currency=GWEN_XMLNode_GetProperty(n, "Ccy", "EUR");
54

  
55
    s=GWEN_XMLNode_GetCharValue(xmlNode, "Amt", NULL);
56
    if (!(s && *s)) {
57
      DBG_ERROR(AQBANKING_LOGDOMAIN, "No data in <BAL/Amt>: [%s]", s);
58
      AB_Balance_free(balance);
59
      return GWEN_ERROR_BAD_DATA;
60
    }
61

  
62
    val=AB_Value_fromString(s);
63
    if (val==NULL) {
64
      DBG_ERROR(AQBANKING_LOGDOMAIN, "Invalid amount in <BAL>: [%s]", s);
65
      AB_Balance_free(balance);
66
      return GWEN_ERROR_BAD_DATA;
67
    }
68
    AB_Value_SetCurrency(val, currency);
69

  
70
    s=GWEN_XMLNode_GetCharValue(xmlNode, "CdtDbtInd", NULL);
71
    if (!(s && *s)) {
72
      DBG_ERROR(AQBANKING_LOGDOMAIN, "Missing <CdtDbtInd> in <BAL>");
73
      AB_Value_free(val);
74
      AB_Balance_free(balance);
75
      return GWEN_ERROR_BAD_DATA;
76
    }
77
    if (strcasecmp(s, "CRDT")==0)
78
      AB_Value_Negate(val);
79

  
80
    AB_Balance_SetValue(balance, val);
81
    AB_Value_free(val);
82
  }
83

  
84
  /* read date */
85
  s=GWEN_XMLNode_GetCharValueByPath(xmlNode, "Dt/Dt", NULL);
86
  if (!(s && *s))
87
    s=GWEN_XMLNode_GetCharValueByPath(xmlNode, "Dt/DtTm", NULL);
88
  if (s && *s) {
89
    GWEN_DATE *dt;
90

  
91
    dt=GWEN_Date_fromStringWithTemplate(s, "YYYY-MM-DD");
92
    if (dt==NULL) {
93
      DBG_ERROR(AQBANKING_LOGDOMAIN, "Invalid date in <BAL>: [%s]", s);
94
      AB_Balance_free(balance);
95
      return GWEN_ERROR_BAD_DATA;
96
    }
97
    AB_Balance_SetDate(balance, dt);
98
    GWEN_Date_free(dt);
99
  }
100

  
101
  /* determine the type of balance, add if acceptable */
102
  s=GWEN_XMLNode_GetCharValueByPath(xmlNode, "Tp/CdOrPrtry/Cd", NULL);
103
  if (s && *s) {
104
    if (strcasecmp(s, "CLBD")==0 ||  /* CLBD: Closing Booked Balance */
105
        strcasecmp(s, "PRCD")==0) {  /* PRCD: Previously Closed Booked Balance */
106
      AB_Balance_SetType(balance, AB_Balance_TypeBooked);
107
      AB_ImExporterAccountInfo_AddBalance(accountInfo, balance);
108
    }
109

  
110
    else if (strcasecmp(s, "CLAV")==0) {
111
      /* CLAV: Closing Available Balance */
112
      AB_Balance_SetType(balance, AB_Balance_TypeDisposable);
113
      AB_ImExporterAccountInfo_AddBalance(accountInfo, balance);
114
    }
115
    else {
116
      DBG_ERROR(AQBANKING_LOGDOMAIN, "Unknown balance type [%s] in <BAL>, ignoring", s);
117
      AB_Balance_free(balance);
118
    }
119
  }
120

  
121
  return 0;
122
}
123

  
124

  
125

  
126
static int _import_052_001_02_read_balances(AB_IMEXPORTER *ie,
127
                                            GWEN_XMLNODE *xmlNode,
128
                                            AB_IMEXPORTER_ACCOUNTINFO *accountInfo) {
129
  GWEN_XMLNODE *n;
130

  
131
  n=GWEN_XMLNode_FindFirstTag(xmlNode, "Bal", NULL, NULL);
132
  while(n) {
133
    int rv;
134

  
135
    rv=_import_052_001_02_read_balance(ie, n, accountInfo);
136
    if (rv<0) {
137
      DBG_INFO(AQBANKING_LOGDOMAIN, "here (%d)", rv);
138
      return rv;
139
    }
140
    n=GWEN_XMLNode_FindNextTag(n, "Bal", NULL, NULL);
141
  } /* while n */
142

  
143
  return 0;
144
}
145

  
146

  
147

  
148
static int _import_052_001_02_read_transaction_details(AB_IMEXPORTER *ie,
149
                                                       GWEN_XMLNODE *xmlNode,
150
                                                       AB_TRANSACTION *t,
151
                                                       int isCredit) {
152
  const char *s;
153
  GWEN_XMLNODE *n;
154

  
155
  s=GWEN_XMLNode_GetCharValueByPath(xmlNode, "Refs/EndToEndId", NULL);
156
  if (s && *s)
157
    AB_Transaction_SetEndToEndReference(t, s);
158

  
159
  /* read names and accounts */
160
  s=GWEN_XMLNode_GetCharValueByPath(xmlNode, "Refs/MndtId", NULL);
161
  if (s && *s)
162
    AB_Transaction_SetMandateId(t, s);
163

  
164
  if (isCredit) {
165
    s=GWEN_XMLNode_GetCharValueByPath(xmlNode, "RltdPties/Dbtr/Nm", NULL);
166
    if (s && *s)
167
      AB_Transaction_SetRemoteName(t, s);
168
    s=GWEN_XMLNode_GetCharValueByPath(xmlNode, "RltdPties/DbtrAcct/Id/IBAN", NULL);
169
    if (s && *s)
170
      AB_Transaction_SetRemoteIban(t, s);
171

  
172
    s=GWEN_XMLNode_GetCharValueByPath(xmlNode, "RltdPties/Cdtr/Nm", NULL);
173
    if (s && *s)
174
      AB_Transaction_SetLocalName(t, s);
175
    s=GWEN_XMLNode_GetCharValueByPath(xmlNode, "RltdPties/CdtrAcct/Id/IBAN", NULL);
176
    if (s && *s)
177
      AB_Transaction_SetLocalIban(t, s);
178
  }
179
  else {
180
    s=GWEN_XMLNode_GetCharValueByPath(xmlNode, "RltdPties/Dbtr/Nm", NULL);
181
    if (s && *s)
182
      AB_Transaction_SetLocalName(t, s);
183
    s=GWEN_XMLNode_GetCharValueByPath(xmlNode, "RltdPties/DbtrAcct/Id/IBAN", NULL);
184
    if (s && *s)
185
      AB_Transaction_SetLocalIban(t, s);
186

  
187
    s=GWEN_XMLNode_GetCharValueByPath(xmlNode, "RltdPties/Cdtr/Nm", NULL);
188
    if (s && *s)
189
      AB_Transaction_SetRemoteName(t, s);
190

  
191
    s=GWEN_XMLNode_GetCharValueByPath(xmlNode, "RltdPties/CdtrAcct/Id/IBAN", NULL);
192
    if (s && *s)
193
      AB_Transaction_SetRemoteIban(t, s);
194

  
195
    s=GWEN_XMLNode_GetCharValueByPath(xmlNode, "RltdPties/Cdtr/Id/PrvtId/Othr/Id", NULL);
196
    if (s && *s)
197
      AB_Transaction_SetOriginatorId(t, s);
198
  }
199

  
200
  /* read transaction codes */
201
  s=GWEN_XMLNode_GetCharValueByPath(xmlNode, "BkTxCd/Domn/Cd", NULL);
202
  if (s && *s) {
203
    GWEN_BUFFER *tbuf;
204

  
205
    tbuf=GWEN_Buffer_new(0, 256, 0, 1);
206
    GWEN_Buffer_AppendString(tbuf, s);
207
    GWEN_Buffer_AppendByte(tbuf, '-');
208

  
209
    s=GWEN_XMLNode_GetCharValueByPath(xmlNode, "BkTxCd/Domn/Fmly/Cd", NULL);
210
    if (s && *s)
211
      GWEN_Buffer_AppendString(tbuf, s);
212
    GWEN_Buffer_AppendByte(tbuf, '-');
213

  
214
    s=GWEN_XMLNode_GetCharValueByPath(xmlNode, "BkTxCd/Domn/Fmly/SubFmlyCd", NULL);
215
    if (s && *s)
216
      GWEN_Buffer_AppendString(tbuf, s);
217

  
218
    AB_Transaction_SetTransactionKey(t, GWEN_Buffer_GetStart(tbuf));
219
    GWEN_Buffer_free(tbuf);
220
  }
221

  
222

  
223
  /* read purpose */
224
  n=GWEN_XMLNode_FindFirstTag(xmlNode, "RmtInf", NULL, NULL);
225
  if(n)
226
    n=GWEN_XMLNode_FindFirstTag(n, "Ustrd", NULL, NULL);
227
  while(n) {
228
    GWEN_XMLNODE *nn;
229

  
230
    nn=GWEN_XMLNode_GetFirstData(n);
231
    if (nn) {
232
      s=GWEN_XMLNode_GetData(nn);
233
      if (s && *s)
234
        AB_Transaction_AddPurposeLine(t, s);
235
    }
236
    n=GWEN_XMLNode_FindNextTag(n, "Ustrd", NULL, NULL);
237
  } /* while n */
238

  
239
  return 0;
240
}
241

  
242

  
243

  
244
static int _import_052_001_02_read_transaction(AB_IMEXPORTER *ie,
245
					       GWEN_XMLNODE *xmlNode,
246
                                               AB_IMEXPORTER_ACCOUNTINFO *accountInfo) {
247
  const char *s;
248
  GWEN_XMLNODE *n;
249
  AB_TRANSACTION *t;
250
  int isCredit=0;
251

  
252
  t=AB_Transaction_new();
253
  AB_Transaction_SetType(t, AB_Transaction_TypeStatement);
254

  
255
  /* read credit/debit mark */
256
  s=GWEN_XMLNode_GetCharValueByPath(xmlNode, "CdtDbtInd", NULL);
257
  if (s && *s) {
258
    if (strcasecmp(s, "DBIT")==0) {
259
      isCredit=0;
260
    }
261
    else if (strcasecmp(s, "CRDT")==0) {
262
      isCredit=1;
263
    }
264
    else {
265
      DBG_ERROR(AQBANKING_LOGDOMAIN, "Invalid CdtDbtInd in <Ntry>: [%s]", s);
266
      AB_Transaction_free(t);
267
      return GWEN_ERROR_BAD_DATA;
268
    }
269
  }
270

  
271
  /* read amount */
272
  n=GWEN_XMLNode_GetNodeByXPath(xmlNode, "Amt", GWEN_PATH_FLAGS_NAMEMUSTEXIST);
273
  if (n) {
274
    const char *currency;
275
    AB_VALUE *val=NULL;
276

  
277
    currency=GWEN_XMLNode_GetProperty(n, "Ccy", "EUR");
278

  
279
    s=GWEN_XMLNode_GetCharValue(xmlNode, "Amt", NULL);
280
    if (!(s && *s)) {
281
      DBG_ERROR(AQBANKING_LOGDOMAIN, "No currency in <Ntry/Amt>: [%s]", s);
282
      AB_Transaction_free(t);
283
      return GWEN_ERROR_BAD_DATA;
284
    }
285

  
286
    val=AB_Value_fromString(s);
287
    if (val==NULL) {
288
      DBG_ERROR(AQBANKING_LOGDOMAIN, "Invalid amount in <Ntry>: [%s]", s);
289
      AB_Transaction_free(t);
290
      return GWEN_ERROR_BAD_DATA;
291
    }
292

  
293
    AB_Value_SetCurrency(val, currency);
294
    if (!isCredit)
295
      AB_Value_Negate(val);
296

  
297
    AB_Transaction_SetValue(t, val);
298
    AB_Value_free(val);
299
  }
300

  
301
  /* read booked date */
302
  s=GWEN_XMLNode_GetCharValueByPath(xmlNode, "BookgDt/Dt", NULL);
303
  if (s && *s) {
304
    GWEN_DATE *dt;
305

  
306
    dt=GWEN_Date_fromStringWithTemplate(s, "YYYY-MM-DD");
307
    if (dt==NULL) {
308
      DBG_ERROR(AQBANKING_LOGDOMAIN, "Invalid booking date in <Ntry>: [%s]", s);
309
      AB_Transaction_free(t);
310
      return GWEN_ERROR_BAD_DATA;
311
    }
312
    AB_Transaction_SetDate(t, dt);
313
    GWEN_Date_free(dt);
314
  }
315

  
316
  /* read valuta date */
317
  s=GWEN_XMLNode_GetCharValueByPath(xmlNode, "ValDt/Dt", NULL);
318
  if (s && *s) {
319
    GWEN_DATE *dt;
320

  
321
    dt=GWEN_Date_fromStringWithTemplate(s, "YYYY-MM-DD");
322
    if (dt==NULL) {
323
      DBG_ERROR(AQBANKING_LOGDOMAIN, "Invalid valuta date in <Ntry>: [%s]", s);
324
      AB_Transaction_free(t);
325
      return GWEN_ERROR_BAD_DATA;
326
    }
327
    AB_Transaction_SetValutaDate(t, dt);
328
    GWEN_Date_free(dt);
329
  }
330

  
331
  /* read bank reference */
332
  s=GWEN_XMLNode_GetCharValueByPath(xmlNode, "NtryRef", NULL);
333
  if (s && *s)
334
    AB_Transaction_SetBankReference(t, s);
335

  
336
  /* read transaction details */
337
  n=GWEN_XMLNode_GetNodeByXPath(xmlNode, "NtryDtls/TxDtls", GWEN_PATH_FLAGS_NAMEMUSTEXIST);
338
  if (n) {
339
    int rv;
340

  
341
    rv=_import_052_001_02_read_transaction_details(ie, n, t, isCredit);
342
    if (rv<0) {
343
      DBG_INFO(AQBANKING_LOGDOMAIN, "here (%d)", rv);
344
      return rv;
345
    }
346
  }
347

  
348
  /* check transaction */
349
  if (!(AB_Transaction_GetValue(t) && (AB_Transaction_GetDate(t) || AB_Transaction_GetValutaDate(t)))) {
350
    DBG_ERROR(AQBANKING_LOGDOMAIN, "Incomplete transaction received");
351
    AB_Transaction_free(t);
352
    return GWEN_ERROR_BAD_DATA;
353
  }
354
  AB_ImExporterAccountInfo_AddTransaction(accountInfo, t);
355

  
356
  return 0;
357
}
358

  
359

  
360

  
361
static int _import_052_001_02_read_transactions(AB_IMEXPORTER *ie,
362
						GWEN_XMLNODE *xmlNode,
363
						AB_IMEXPORTER_ACCOUNTINFO *accountInfo) {
364
  GWEN_XMLNODE *n;
365

  
366
  n=GWEN_XMLNode_FindFirstTag(xmlNode, "Ntry", NULL, NULL);
367
  while(n) {
368
    int rv;
369

  
370
    rv=_import_052_001_02_read_transaction(ie, n, accountInfo);
371
    if (rv<0) {
372
      DBG_INFO(AQBANKING_LOGDOMAIN, "here (%d)", rv);
373
      return rv;
374
    }
375
    n=GWEN_XMLNode_FindNextTag(n, "Ntry", NULL, NULL);
376
  } /* while n */
377

  
378
  return 0;
379
}
380

  
381

  
382

  
383
static int _import_052_001_02_report(AB_IMEXPORTER *ie,
384
                                     AB_IMEXPORTER_CONTEXT *ctx,
385
                                     GWEN_DB_NODE *params,
386
                                     GWEN_XMLNODE *xmlNode) {
387
  GWEN_XMLNODE *n;
388
  AB_IMEXPORTER_ACCOUNTINFO *accountInfo=NULL;
389
  int rv;
390

  
391
  /* read account, set accountInfo */
392
  n=GWEN_XMLNode_FindFirstTag(xmlNode, "Acct", NULL, NULL);
393
  if (n) {
394
    AB_ACCOUNT_SPEC *accountSpec;
395

  
396
    accountSpec=AB_AccountSpec_new();
397
    _import_052_001_02_read_account_spec(ie, n, accountSpec);
398
    accountInfo=AB_ImExporterContext_GetOrAddAccountInfo(ctx,
399
							 0,
400
							 AB_AccountSpec_GetIban(accountSpec),
401
							 AB_AccountSpec_GetBankCode(accountSpec),
402
							 AB_AccountSpec_GetAccountNumber(accountSpec),
403
							 AB_AccountType_Unknown);
404
    assert(accountInfo);
405
    AB_AccountSpec_free(accountSpec);
406
  }
407

  
408
  /* read balances */
409
  rv=_import_052_001_02_read_balances(ie, xmlNode, accountInfo);
410
  if (rv<0) {
411
    DBG_INFO(AQBANKING_LOGDOMAIN, "here (%d)", rv);
412
    return rv;
413
  }
414

  
415
  /* read transactions */
416
  rv=_import_052_001_02_read_transactions(ie, xmlNode, accountInfo);
417
  if (rv<0) {
418
    DBG_INFO(AQBANKING_LOGDOMAIN, "here (%d)", rv);
419
    return rv;
420
  }
421

  
422
  return 0;
423
}
424

  
425

  
426

  
427

  
428

  
429
int AH_ImExporterCAMT_Import_052_001_02(AB_IMEXPORTER *ie,
430
                                        AB_IMEXPORTER_CONTEXT *ctx,
431
                                        GWEN_DB_NODE *params,
432
                                        GWEN_XMLNODE *xmlNode) {
433
  GWEN_XMLNODE *n;
434

  
435
  n=GWEN_XMLNode_FindFirstTag(xmlNode, "BkToCstmrAcctRpt", NULL, NULL);
436
  if (n==NULL) {
437
    DBG_ERROR(AQBANKING_LOGDOMAIN, "<BkToCstmrAcctRpt> element not found");
438
    return GWEN_ERROR_BAD_DATA;
439
  }
440

  
441
  n=GWEN_XMLNode_FindFirstTag(n, "Rpt", NULL, NULL);
442
  if (n==NULL) {
443
    DBG_ERROR(AQBANKING_LOGDOMAIN, "<Rpt> element not found");
444
    return GWEN_ERROR_BAD_DATA;
445
  }
446

  
447
  /* now read every report */
448
  while(n) {
449
    int rv;
450

  
451
    rv=_import_052_001_02_report(ie, ctx, params, n);
452
    if (rv<0) {
453
      DBG_INFO(AQBANKING_LOGDOMAIN, "here (%d)", rv);
454
      return rv;
455
    }
456
    n=GWEN_XMLNode_FindNextTag(n, "Rpt", NULL, NULL);
457
  }
458
  return 0;
459
}
460

  
461

  
462

  
463

  
src/libs/plugins/imexporters/camt/camt_p.h
1
/***************************************************************************
2
    begin       : Sat Dec 15 2018
3
    copyright   : (C) 2018 by Martin Preuss
4
    email       : martin@libchipcard.de
5

  
6
 ***************************************************************************
7
 *          Please see toplevel file COPYING for license details           *
8
 ***************************************************************************/
9

  
10

  
11
#ifndef AQBANKING_IMEX_CAMT_P_H
12
#define AQBANKING_IMEX_CAMT_P_H
13

  
14

  
15
#include "camt.h"
16

  
17
#include <aqbanking/imexporter_be.h>
18

  
19

  
20
typedef struct AH_IMEXPORTER_CAMT AH_IMEXPORTER_CAMT;
21
struct AH_IMEXPORTER_CAMT {
22
  int dummy;
23
};
24

  
25

  
26
static void GWENHYWFAR_CB AH_ImExporterCAMT_FreeData(void *bp, void *p);
27

  
28
static int AH_ImExporterCAMT_Import(AB_IMEXPORTER *ie,
29
                                    AB_IMEXPORTER_CONTEXT *ctx,
30
                                    GWEN_SYNCIO *sio,
31
                                    GWEN_DB_NODE *params);
32

  
33
static int AH_ImExporterCAMT_Export(AB_IMEXPORTER *ie,
34
                                    AB_IMEXPORTER_CONTEXT *ctx,
35
                                    GWEN_SYNCIO *sio,
36
                                    GWEN_DB_NODE *params);
37

  
38
static int AH_ImExporterCAMT_CheckFile(AB_IMEXPORTER *ie, const char *fname);
39

  
40

  
41
static int AH_ImExporterCAMT_Import_052_001_02(AB_IMEXPORTER *ie,
42
                                               AB_IMEXPORTER_CONTEXT *ctx,
43
                                               GWEN_DB_NODE *params,
44
                                               GWEN_XMLNODE *xmlRoot);
45

  
46

  
47

  
48
#endif /* AQBANKING_IMEX_CAMT_P_H */
src/libs/plugins/imexporters/camt/profiles/052_001_02.conf.in
1

  
2
char name="052_001_02"
3
char shortDescr="camt.052.001.02"
4
char version="@AQBANKING_VERSION_STRING@"
5
char longDescr="Profile for pain.001.001.02 (sepade rather than ISO version)"
6
int import="0"
7
int export="1"
8

  
9
char type="052.001.02"
10

  
11
# XML namespace of the pain messages handled by this profile
12
char xmlns="urn:iso:std:iso:20022:tech:xsd:camt.052.001.02"
13

  
src/libs/plugins/imexporters/camt/profiles/Makefile.am
1

  
2
EXTRA_DIST=\
3
 default.conf.in \
4
 052_001_02_conf.in
5

  
6
profilesdir = $(aqbanking_pkgdatadir)/imexporters/camt/profiles
7
profiles_DATA=default.conf 052_001_02.conf
8

  
src/libs/plugins/imexporters/camt/profiles/default.conf.in
1

  
2
char name="default"
3
char shortDescr="default profile"
4
char version="@AQBANKING_VERSION_STRING@"
5
char longDescr="This profile supports transfers"
6
int import="0"
7
int export="1"
8

  
9
char type="052.001.02"
10

  
11
# XML namespace of the pain messages handled by this profile
12
char xmlns="urn:iso:std:iso:20022:tech:xsd:camt.052.001.02"
13

  
src/libs/plugins/imexporters/ofx/parser/g_bal.c
64 64
  xg=(AIO_OFX_GROUP_BAL*)p;
65 65
  assert(xg);
66 66
  free(xg->currentElement);
67
  GWEN_Time_free(xg->date);
67
  GWEN_Date_free(xg->date);
68 68
  AB_Value_free(xg->value);
69 69
  GWEN_FREE_OBJECT(xg);
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff