~ubuntu-branches/ubuntu/lucid/skrooge/lucid

« back to all changes in this revision

Viewing changes to skgbankmodeler/skgimportexportmanager.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Mercatante
  • Date: 2009-05-02 06:47:15 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20090502064715-b7l4eciitw3asos3
Tags: 0.2.7-0ubuntu1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
45
45
{
46
46
        setDefaultAccount(NULL);
47
47
        setDefaultUnit(NULL);
 
48
        document=NULL;
 
49
        defaultAccount=NULL;
 
50
        defaultUnit=NULL;
48
51
}
49
52
 
50
53
SKGDocumentBank* SKGImportExportManager::getDocument()
75
78
{
76
79
        SKGError err;
77
80
        SKGTRACEINRC(10, "SKGImportExportManager::getDefaultAccount", err);
78
 
        if (defaultAccount==NULL) {
 
81
        if (defaultAccount==NULL && document) {
79
82
                QFileInfo fInfo(fileName);
80
83
                QString name=fInfo.baseName();
81
84
 
111
114
{
112
115
        SKGError err;
113
116
        SKGTRACEINRC(10, "SKGImportExportManager::getDefaultUnit", err);
114
 
        if (defaultUnit==NULL || iDate) {
 
117
        if (document && (defaultUnit==NULL || iDate)) {
115
118
                if (defaultUnit==NULL) {
116
119
                        delete defaultUnit;
117
120
                        defaultUnit=NULL;
207
210
        SKGTRACEINRC(2, "SKGImportExportManager::exportQIF", err);
208
211
        SKGTRACEL(10) << "Input filename=" << fileName << endl;
209
212
 
210
 
        //Open file
211
 
        QFile file(fileName);
212
 
        if (!file.open(QIODevice::WriteOnly)) {
213
 
                err.setReturnCode(ERR_INVALIDARG);
214
 
                err.setMessage(tr("Save file [%1] failed").arg(fileName));
215
 
        } else {
216
 
                QTextStream stream(&file);
217
 
                SKGTRACEL(2) << "Text codec=" << QTextCodec::codecForLocale ()->name() << endl;
218
 
 
219
 
                err=document->beginTransaction("#INTERNAL#", 2);
220
 
                if (err.isSucceeded()) {
221
 
 
222
 
                        //Export categories
223
 
                        SKGObjectBase::SKGListSKGObjectBase categories;
224
 
                        if (err.isSucceeded()) err=SKGObjectBase::getObjects(document, "v_category_display_tmp", "1=1 ORDER BY t_fullname, id", categories);
225
 
                        int nbcat=categories.count();
226
 
                        if (err.isSucceeded() && nbcat) {
227
 
                                stream << "!Type:Cat\n";
228
 
                                err=document->beginTransaction("#INTERNAL#", nbcat);
229
 
                                for (int i=0; err.isSucceeded() && i<nbcat; ++i) {
230
 
                                        SKGCategoryObject cat=categories.at(i);
231
 
                                        stream << "N" << cat.getFullName() << endl;
232
 
                                        if (SKGServices::stringToDouble(cat.getAttribute("f_REALCURRENTAMOUNT"))<0) {
233
 
                                                stream << "E" << endl;
234
 
                                        } else {
235
 
                                                stream << "I" << endl;
 
213
        if (document) {
 
214
                //Open file
 
215
                QFile file(fileName);
 
216
                if (!file.open(QIODevice::WriteOnly)) {
 
217
                        err.setReturnCode(ERR_INVALIDARG);
 
218
                        err.setMessage(tr("Save file [%1] failed").arg(fileName));
 
219
                } else {
 
220
                        QTextStream stream(&file);
 
221
                        SKGTRACEL(2) << "Text codec=" << QTextCodec::codecForLocale ()->name() << endl;
 
222
 
 
223
                        err=document->beginTransaction("#INTERNAL#", 2);
 
224
                        if (err.isSucceeded()) {
 
225
 
 
226
                                //Export categories
 
227
                                SKGObjectBase::SKGListSKGObjectBase categories;
 
228
                                if (err.isSucceeded()) err=SKGObjectBase::getObjects(document, "v_category_display_tmp", "1=1 ORDER BY t_fullname, id", categories);
 
229
                                int nbcat=categories.count();
 
230
                                if (err.isSucceeded() && nbcat) {
 
231
                                        stream << "!Type:Cat\n";
 
232
                                        err=document->beginTransaction("#INTERNAL#", nbcat);
 
233
                                        for (int i=0; err.isSucceeded() && i<nbcat; ++i) {
 
234
                                                SKGCategoryObject cat=categories.at(i);
 
235
                                                stream << "N" << cat.getFullName() << endl;
 
236
                                                if (SKGServices::stringToDouble(cat.getAttribute("f_REALCURRENTAMOUNT"))<0) {
 
237
                                                        stream << "E" << endl;
 
238
                                                } else {
 
239
                                                        stream << "I" << endl;
 
240
                                                }
 
241
                                                stream << "^" << endl;
 
242
                                                if (err.isSucceeded()) err=document->stepForward(i+1);
236
243
                                        }
237
 
                                        stream << "^" << endl;
238
 
                                        if (err.isSucceeded()) err=document->stepForward(i+1);
 
244
 
 
245
                                        if (err.isSucceeded()) err=document->endTransaction(true);
 
246
                                        else  document->endTransaction(false);
239
247
                                }
240
 
 
241
 
                                if (err.isSucceeded()) err=document->endTransaction(true);
242
 
                                else  document->endTransaction(false);
243
 
                        }
244
 
                        if (err.isSucceeded()) err=document->stepForward(1);
245
 
 
246
 
                        //Get operations
247
 
                        QString currentAccountName;
248
 
                        SKGObjectBase::SKGListSKGObjectBase operations;
249
 
                        if (err.isSucceeded()) err=SKGObjectBase::getObjects(document, "v_operation_display", "1=1 ORDER BY t_ACCOUNT, d_date, id", operations);
250
 
                        int nb=operations.count();
251
 
                        if (err.isSucceeded()) {
252
 
                                err=document->beginTransaction("#INTERNAL#", nb);
253
 
                                for (int i=0; err.isSucceeded() && i<nb; ++i) {
254
 
                                        SKGOperationObject operation=operations.at(i);
255
 
 
256
 
                                        //Get account name
257
 
                                        QString accountName=operation.getAttribute("t_ACCOUNT");
258
 
 
259
 
                                        //In the same account ?
260
 
                                        if (accountName!=currentAccountName) {
261
 
                                                SKGAccountObject account(document);
262
 
                                                account.setName(accountName);
263
 
                                                account.load();
264
 
 
265
 
                                                SKGBankObject bank;
266
 
                                                account.getBank(bank);
267
 
 
268
 
                                                //Write header
269
 
                                                stream << "!Account\n";
270
 
                                                stream << 'N' << accountName << endl;
271
 
                                                stream << 'T' << account.getType() << endl;
272
 
                                                QString number=bank.getNumber();
273
 
                                                QString bnumber=account.getAgencyNumber();
274
 
                                                QString cnumber=account.getNumber();
275
 
                                                if (!bnumber.isEmpty()) {
276
 
                                                        if (!number.isEmpty()) number+='-';
277
 
                                                        number+=bnumber;
278
 
                                                }
279
 
                                                if (!cnumber.isEmpty()) {
280
 
                                                        if (!number.isEmpty()) number+='-';
281
 
                                                        number+=cnumber;
282
 
                                                }
283
 
                                                stream << 'D' << number << endl;
284
 
                                                //stream << "/"      Statement balance date
285
 
                                                //stream << "$"      Statement balance amount
286
 
                                                stream << '^' << endl;
287
 
                                                currentAccountName=accountName;
288
 
 
289
 
                                                stream << "!Type:Bank\n";
290
 
                                        }
291
 
 
292
 
 
293
 
                                        //Write operation
294
 
                                        /*
295
 
                                        DONE    D      Date
296
 
                                        DONE    T      Amount
297
 
                                        N/A     U      Transaction amount (higher possible value than T)
298
 
                                        DONE    C      Cleared status
299
 
                                        DONE    N      Number (check or reference number)
300
 
                                        DONE    P      Payee/description
301
 
                                        DONE    M      Memo
302
 
                                        N/A     A      Address (up to 5 lines; 6th line is an optional message)
303
 
                                        DONE    L      Category (category/class or transfer/class)
304
 
                                        DONE    S      Category in split (category/class or transfer/class)
305
 
                                        N/A     E      Memo in split
306
 
                                        DONE    $      Dollar amount of split
307
 
                                        N/A     %      Percentage of split if percentages are used
308
 
                                        N/A     F      Reimbursable business expense flag
309
 
                                        N/A     X      Small Business extensions
310
 
                                        DONE    ^      End of entry
311
 
                                        */
312
 
 
313
 
                                        stream << 'D' << SKGServices::dateToSqlString(QDateTime(operation.getDate())) << endl;
314
 
                                        stream << 'T' << SKGServices::doubleToString(operation.getCurrentAmount()) << endl;
315
 
 
316
 
                                        int number=operation.getNumber();
317
 
                                        if (number) stream << 'N' << operation.getNumber() << endl;
318
 
 
319
 
                                        QString payee=operation.getPayee();
320
 
                                        if (payee.length()) stream << 'P' << payee << endl;
321
 
 
322
 
                                        QString memo=operation.getMode()+"  "+operation.getComment();
323
 
                                        memo=memo.trimmed();
324
 
                                        if (memo.length()) stream << 'M' << memo << endl;
325
 
 
326
 
                                        SKGOperationObject::OperationStatus status=operation.getStatus();
327
 
                                        stream << "C" << (status==SKGOperationObject::POINTED ? "C": (status==SKGOperationObject::CHECKED ? "R": "" )) << endl;
328
 
 
329
 
                                        //Get sub operations
330
 
                                        SKGObjectBase::SKGListSKGObjectBase suboperations;
331
 
                                        err=operation.getSubOperations(suboperations);
332
 
                                        if (err.isSucceeded()) {
333
 
                                                int nb=suboperations.size();
334
 
                                                if (nb>1) {
335
 
                                                        //Splitted operation
336
 
                                                        for (int i=0; i<nb; ++i) {
337
 
                                                                SKGSubOperationObject suboperation=suboperations.at(i);
 
248
                                if (err.isSucceeded()) err=document->stepForward(1);
 
249
 
 
250
                                //Get operations
 
251
                                QString currentAccountName;
 
252
                                SKGObjectBase::SKGListSKGObjectBase operations;
 
253
                                if (err.isSucceeded()) err=SKGObjectBase::getObjects(document, "v_operation_display", "1=1 ORDER BY t_ACCOUNT, d_date, id", operations);
 
254
                                int nb=operations.count();
 
255
                                if (err.isSucceeded()) {
 
256
                                        err=document->beginTransaction("#INTERNAL#", nb);
 
257
                                        for (int i=0; err.isSucceeded() && i<nb; ++i) {
 
258
                                                SKGOperationObject operation=operations.at(i);
 
259
 
 
260
                                                //Get account name
 
261
                                                QString accountName=operation.getAttribute("t_ACCOUNT");
 
262
 
 
263
                                                //In the same account ?
 
264
                                                if (accountName!=currentAccountName) {
 
265
                                                        SKGAccountObject account(document);
 
266
                                                        account.setName(accountName);
 
267
                                                        account.load();
 
268
 
 
269
                                                        SKGBankObject bank;
 
270
                                                        account.getBank(bank);
 
271
 
 
272
                                                        //Write header
 
273
                                                        stream << "!Account\n";
 
274
                                                        stream << 'N' << accountName << endl;
 
275
                                                        stream << 'T' << account.getType() << endl;
 
276
                                                        QString number=bank.getNumber();
 
277
                                                        QString bnumber=account.getAgencyNumber();
 
278
                                                        QString cnumber=account.getNumber();
 
279
                                                        if (!bnumber.isEmpty()) {
 
280
                                                                if (!number.isEmpty()) number+='-';
 
281
                                                                number+=bnumber;
 
282
                                                        }
 
283
                                                        if (!cnumber.isEmpty()) {
 
284
                                                                if (!number.isEmpty()) number+='-';
 
285
                                                                number+=cnumber;
 
286
                                                        }
 
287
                                                        stream << 'D' << number << endl;
 
288
                                                        //stream << "/"      Statement balance date
 
289
                                                        //stream << "$"      Statement balance amount
 
290
                                                        stream << '^' << endl;
 
291
                                                        currentAccountName=accountName;
 
292
 
 
293
                                                        stream << "!Type:Bank\n";
 
294
                                                }
 
295
 
 
296
 
 
297
                                                //Write operation
 
298
                                                /*
 
299
                                                DONE    D      Date
 
300
                                                DONE    T      Amount
 
301
                                                N/A     U      Transaction amount (higher possible value than T)
 
302
                                                DONE    C      Cleared status
 
303
                                                DONE    N      Number (check or reference number)
 
304
                                                DONE    P      Payee/description
 
305
                                                DONE    M      Memo
 
306
                                                N/A     A      Address (up to 5 lines; 6th line is an optional message)
 
307
                                                DONE    L      Category (category/class or transfer/class)
 
308
                                                DONE    S      Category in split (category/class or transfer/class)
 
309
                                                N/A     E      Memo in split
 
310
                                                DONE    $      Dollar amount of split
 
311
                                                N/A     %      Percentage of split if percentages are used
 
312
                                                N/A     F      Reimbursable business expense flag
 
313
                                                N/A     X      Small Business extensions
 
314
                                                DONE    ^      End of entry
 
315
                                                */
 
316
 
 
317
                                                stream << 'D' << SKGServices::dateToSqlString(QDateTime(operation.getDate())) << endl;
 
318
                                                stream << 'T' << SKGServices::doubleToString(operation.getCurrentAmount()) << endl;
 
319
 
 
320
                                                int number=operation.getNumber();
 
321
                                                if (number) stream << 'N' << operation.getNumber() << endl;
 
322
 
 
323
                                                QString payee=operation.getPayee();
 
324
                                                if (payee.length()) stream << 'P' << payee << endl;
 
325
 
 
326
                                                QString memo=operation.getMode()+"  "+operation.getComment();
 
327
                                                memo=memo.trimmed();
 
328
                                                if (memo.length()) stream << 'M' << memo << endl;
 
329
 
 
330
                                                SKGOperationObject::OperationStatus status=operation.getStatus();
 
331
                                                stream << "C" << (status==SKGOperationObject::POINTED ? "C": (status==SKGOperationObject::CHECKED ? "R": "" )) << endl;
 
332
 
 
333
                                                //Get sub operations
 
334
                                                SKGObjectBase::SKGListSKGObjectBase suboperations;
 
335
                                                err=operation.getSubOperations(suboperations);
 
336
                                                if (err.isSucceeded()) {
 
337
                                                        int nb=suboperations.size();
 
338
                                                        if (nb>1) {
 
339
                                                                //Splitted operation
 
340
                                                                for (int i=0; i<nb; ++i) {
 
341
                                                                        SKGSubOperationObject suboperation=suboperations.at(i);
 
342
                                                                        SKGCategoryObject cat;
 
343
                                                                        suboperation.getCategory(cat);
 
344
 
 
345
                                                                        QString category=cat.getFullName();
 
346
                                                                        if (category.length()) stream << 'S' << category << endl;
 
347
                                                                        stream << '$' << SKGServices::doubleToString(suboperation.getQuantity()) << endl;
 
348
                                                                }
 
349
                                                        } else if (nb==1) {
 
350
                                                                //Simple operation
 
351
                                                                SKGSubOperationObject suboperation=suboperations.at(0);
338
352
                                                                SKGCategoryObject cat;
339
353
                                                                suboperation.getCategory(cat);
340
354
 
341
355
                                                                QString category=cat.getFullName();
342
 
                                                                if (category.length()) stream << 'S' << category << endl;
343
 
                                                                stream << '$' << SKGServices::doubleToString(suboperation.getQuantity()) << endl;
 
356
                                                                if (category.length()) stream << 'L' << category << endl;
344
357
                                                        }
345
 
                                                } else if (nb==1) {
346
 
                                                        //Simple operation
347
 
                                                        SKGSubOperationObject suboperation=suboperations.at(0);
348
 
                                                        SKGCategoryObject cat;
349
 
                                                        suboperation.getCategory(cat);
350
 
 
351
 
                                                        QString category=cat.getFullName();
352
 
                                                        if (category.length()) stream << 'L' << category << endl;
353
358
                                                }
 
359
 
 
360
                                                stream << '^' << endl;
 
361
                                                if (err.isSucceeded()) err=document->stepForward(i+1);
354
362
                                        }
355
363
 
356
 
                                        stream << '^' << endl;
357
 
                                        if (err.isSucceeded()) err=document->stepForward(i+1);
 
364
                                        if (err.isSucceeded()) err=document->endTransaction(true);
 
365
                                        else  document->endTransaction(false);
358
366
                                }
359
 
 
 
367
                                if (err.isSucceeded()) err=document->stepForward(2);
360
368
                                if (err.isSucceeded()) err=document->endTransaction(true);
361
369
                                else  document->endTransaction(false);
362
370
                        }
363
 
                        if (err.isSucceeded()) err=document->stepForward(2);
364
 
                        if (err.isSucceeded()) err=document->endTransaction(true);
365
 
                        else  document->endTransaction(false);
366
371
                }
 
372
 
 
373
                //Close file
 
374
                file.close();
367
375
        }
368
376
 
369
 
        //Close file
370
 
        file.close();
371
 
 
372
377
        if (err.isFailed()) {
373
378
                err.addError(ERR_FAIL, tr("%1 failed").arg("SKGImportExportManager::exportQIF"));
374
379
        }
381
386
        SKGTRACEINRC(2, "SKGDocumentBank::exportCSV", err);
382
387
        SKGTRACEL(10) << "Input filename=" << fileName << endl;
383
388
 
384
 
        //Open file
385
 
        QFile file(fileName);
386
 
        if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
387
 
                err.setReturnCode(ERR_INVALIDARG);
388
 
                err.setMessage(tr("Save file [%1] failed").arg(fileName));
389
 
        } else {
390
 
                QTextStream out(&file);
391
 
                err=SKGServices::dumpSelectSqliteOrder((SKGDocument*) document,
392
 
                                                       "SELECT d_date as date, t_ACCOUNT as account, i_number as number, t_mode as mode, "
393
 
                                                       "t_payee as payee, t_comment as comment, f_QUANTITY as quantity, "
394
 
                                                       "t_UNIT as unit, f_CURRENTAMOUNT as amount, t_TYPEEXPENSE as sign, t_CATEGORY as category, t_status as status, "
395
 
                                                       "t_bookmarked as bookmarked "
396
 
                                                       "FROM v_operation_display", &out, SKGServices::DUMP_CSV);
 
389
        if (document) {
 
390
                //Open file
 
391
                QFile file(fileName);
 
392
                if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
 
393
                        err.setReturnCode(ERR_INVALIDARG);
 
394
                        err.setMessage(tr("Save file [%1] failed").arg(fileName));
 
395
                } else {
 
396
                        QTextStream out(&file);
 
397
                        err=SKGServices::dumpSelectSqliteOrder((SKGDocument*) document,
 
398
                                                               "SELECT d_date as date, t_ACCOUNT as account, i_number as number, t_mode as mode, "
 
399
                                                               "t_payee as payee, t_comment as comment, f_QUANTITY as quantity, "
 
400
                                                               "t_UNIT as unit, f_CURRENTAMOUNT as amount, t_TYPEEXPENSE as sign, t_CATEGORY as category, t_status as status, "
 
401
                                                               "t_bookmarked as bookmarked "
 
402
                                                               "FROM v_operation_display", &out, SKGServices::DUMP_CSV);
 
403
                }
 
404
 
 
405
                //Close file
 
406
                file.close();
397
407
        }
398
408
 
399
 
        //Close file
400
 
        file.close();
401
 
 
402
409
        if (err.isFailed()) {
403
410
                err.addError(ERR_FAIL, tr("%1 failed").arg("SKGImportExportManager::exportQIF"));
404
411
        }
561
568
        SKGTRACEINRC(2, "SKGImportExportManager::importCSVUnit", err);
562
569
        SKGTRACEL(10) << "Input filename=" << fileName << endl;
563
570
 
564
 
        //Begin transaction
565
 
        err=document->beginTransaction("#INTERNAL#", 3);
566
 
        if (err.isSucceeded()) {
567
 
                //File name is the name of the unit
568
 
                QFileInfo fInfo(fileName);
569
 
                QString unitName=fInfo.baseName();
570
 
 
571
 
                //Default mapping
572
 
                if (getCSVMapping().count()==0) {
573
 
                        err= setCSVMapping(NULL);
574
 
                        if (err.isSucceeded()) err=document->sendMessage(tr("Use automatic CSV mapping detection"));
575
 
                }
576
 
 
577
 
                //Step 1 done
578
 
                if (err.isSucceeded()) err=document->stepForward(1);
579
 
 
580
 
                //Open file
 
571
        if (document) {
 
572
                //Begin transaction
 
573
                err=document->beginTransaction("#INTERNAL#", 3);
581
574
                if (err.isSucceeded()) {
582
 
                        QFile file(fileName);
583
 
                        if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
584
 
                                err.setReturnCode(ERR_INVALIDARG);
585
 
                                err.setMessage(tr("Open file [%1] failed").arg(fileName));
586
 
                        } else {
587
 
                                QTextStream stream(&file);
588
 
                                if (!codec.isEmpty()) stream.setCodec(codec.toAscii().constData());
589
 
 
590
 
                                //Ignore useless lines
591
 
                                int headerIndex=getCSVHeaderIndex();
592
 
                                for (int i=0; i<=headerIndex; ++i)
593
 
                                        stream.readLine();
594
 
 
595
 
                                //Get data column
596
 
                                QStringList dates;
597
 
                                QStringList lines;
598
 
                                int posdate=csvMapping.indexOf("date");
599
 
                                if (posdate!=-1) {
600
 
                                        while (!stream.atEnd()) {
601
 
                                                //Read line
602
 
                                                QString line=stream.readLine().trimmed();
603
 
                                                if (!line.isEmpty()) {
604
 
                                                        lines.push_back(line);
605
 
 
606
 
                                                        //Get date
607
 
                                                        QStringList field=SKGServices::splitCSVLine(line);
608
 
                                                        if (posdate<field.count()) dates.push_back(field.at(posdate));
609
 
                                                }
610
 
                                        }
611
 
                                }
612
 
 
613
 
                                //close file
614
 
                                file.close();
615
 
 
616
 
                                //Select dateformat
617
 
                                QString dateFormat=SKGServices::getDateFormat(dates);
618
 
                                if (dateFormat.isEmpty()) {
619
 
                                        err.setReturnCode(ERR_FAIL);
620
 
                                        err.setMessage(tr("Date format not supported"));
621
 
                                }
622
 
                                if (err.isSucceeded())
623
 
                                        err=document->sendMessage(tr("Import of [%1] with code [%2] and date format [%3]").arg(fileName).arg(codec).arg(dateFormat));
624
 
 
625
 
                                //Step 2 done
626
 
                                if (err.isSucceeded()) err=document->stepForward(2);
627
 
 
628
 
                                //Treat all lines
629
 
                                if (err.isSucceeded()) {
630
 
                                        int nb=lines.size();
631
 
                                        err=document->beginTransaction("#INTERNAL#", nb);
632
 
 
633
 
                                        //Save last mapping used in a settings
634
 
                                        QString mappingDesc;
635
 
                                        int nbMap=csvMapping.count();
636
 
                                        for (int i=0; i<nbMap;++i) {
637
 
                                                if (i) mappingDesc+='|';
638
 
                                                mappingDesc+=csvMapping.at(i);
639
 
                                        }
640
 
                                        if (err.isSucceeded()) err=document->setParameter("SKG_LAST_CSV_UNIT_MAPPING_USED", mappingDesc);
641
 
 
 
575
                        //File name is the name of the unit
 
576
                        QFileInfo fInfo(fileName);
 
577
                        QString unitName=fInfo.baseName();
 
578
 
 
579
                        //Default mapping
 
580
                        if (getCSVMapping().count()==0) {
 
581
                                err= setCSVMapping(NULL);
 
582
                                if (err.isSucceeded()) err=document->sendMessage(tr("Use automatic CSV mapping detection"));
 
583
                        }
 
584
 
 
585
                        //Step 1 done
 
586
                        if (err.isSucceeded()) err=document->stepForward(1);
 
587
 
 
588
                        //Open file
 
589
                        if (err.isSucceeded()) {
 
590
                                QFile file(fileName);
 
591
                                if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
 
592
                                        err.setReturnCode(ERR_INVALIDARG);
 
593
                                        err.setMessage(tr("Open file [%1] failed").arg(fileName));
 
594
                                } else {
 
595
                                        QTextStream stream(&file);
 
596
                                        if (!codec.isEmpty()) stream.setCodec(codec.toAscii().constData());
 
597
 
 
598
                                        //Ignore useless lines
 
599
                                        int headerIndex=getCSVHeaderIndex();
 
600
                                        for (int i=0; i<=headerIndex; ++i)
 
601
                                                stream.readLine();
 
602
 
 
603
                                        //Get data column
 
604
                                        QStringList dates;
 
605
                                        QStringList lines;
642
606
                                        int posdate=csvMapping.indexOf("date");
643
 
                                        int posvalue=csvMapping.indexOf("amount");
644
 
                                        if (posdate!=-1 && posvalue!=-1) {
645
 
                                                for (int i = 0; err.isSucceeded() && i < nb; ++i) {
646
 
                                                        QStringList atts=SKGServices::splitCSVLine(lines.at(i));
647
 
                                                        err=document->addOrModifyUnitValue(unitName,
648
 
                                                                                           SKGServices::stringToTime(SKGServices::dateToSqlString(atts.at(posdate), dateFormat)).date(),
649
 
                                                                                           SKGServices::stringToDouble(atts.at(posvalue)));
650
 
 
651
 
                                                        if (err.isSucceeded()) err=document->stepForward(i+1);
652
 
                                                }
653
 
                                        }
654
 
 
655
 
                                        if (err.isSucceeded()) err=document->endTransaction(true);
656
 
                                        else  document->endTransaction(false);
657
 
 
658
 
                                        //Lines treated
659
 
                                        if (err.isSucceeded()) err=document->stepForward(3);
 
607
                                        if (posdate!=-1) {
 
608
                                                while (!stream.atEnd()) {
 
609
                                                        //Read line
 
610
                                                        QString line=stream.readLine().trimmed();
 
611
                                                        if (!line.isEmpty()) {
 
612
                                                                lines.push_back(line);
 
613
 
 
614
                                                                //Get date
 
615
                                                                QStringList field=SKGServices::splitCSVLine(line);
 
616
                                                                if (posdate<field.count()) dates.push_back(field.at(posdate));
 
617
                                                        }
 
618
                                                }
 
619
                                        }
 
620
 
 
621
                                        //close file
 
622
                                        file.close();
 
623
 
 
624
                                        //Select dateformat
 
625
                                        QString dateFormat=SKGServices::getDateFormat(dates);
 
626
                                        if (dateFormat.isEmpty()) {
 
627
                                                err.setReturnCode(ERR_FAIL);
 
628
                                                err.setMessage(tr("Date format not supported"));
 
629
                                        }
 
630
                                        if (err.isSucceeded())
 
631
                                                err=document->sendMessage(tr("Import of [%1] with code [%2] and date format [%3]").arg(fileName).arg(codec).arg(dateFormat));
 
632
 
 
633
                                        //Step 2 done
 
634
                                        if (err.isSucceeded()) err=document->stepForward(2);
 
635
 
 
636
                                        //Treat all lines
 
637
                                        if (err.isSucceeded()) {
 
638
                                                int nb=lines.size();
 
639
                                                err=document->beginTransaction("#INTERNAL#", nb);
 
640
 
 
641
                                                //Save last mapping used in a settings
 
642
                                                QString mappingDesc;
 
643
                                                int nbMap=csvMapping.count();
 
644
                                                for (int i=0; i<nbMap;++i) {
 
645
                                                        if (i) mappingDesc+='|';
 
646
                                                        mappingDesc+=csvMapping.at(i);
 
647
                                                }
 
648
                                                if (err.isSucceeded()) err=document->setParameter("SKG_LAST_CSV_UNIT_MAPPING_USED", mappingDesc);
 
649
 
 
650
                                                int posdate=csvMapping.indexOf("date");
 
651
                                                int posvalue=csvMapping.indexOf("amount");
 
652
                                                if (posdate!=-1 && posvalue!=-1) {
 
653
                                                        for (int i = 0; err.isSucceeded() && i < nb; ++i) {
 
654
                                                                QStringList atts=SKGServices::splitCSVLine(lines.at(i));
 
655
                                                                err=document->addOrModifyUnitValue(unitName,
 
656
                                                                                                   SKGServices::stringToTime(SKGServices::dateToSqlString(atts.at(posdate), dateFormat)).date(),
 
657
                                                                                                   SKGServices::stringToDouble(atts.at(posvalue)));
 
658
 
 
659
                                                                if (err.isSucceeded()) err=document->stepForward(i+1);
 
660
                                                        }
 
661
                                                }
 
662
 
 
663
                                                if (err.isSucceeded()) err=document->endTransaction(true);
 
664
                                                else  document->endTransaction(false);
 
665
 
 
666
                                                //Lines treated
 
667
                                                if (err.isSucceeded()) err=document->stepForward(3);
 
668
                                        }
660
669
                                }
661
670
                        }
662
671
                }
 
672
                if (err.isSucceeded()) err=document->endTransaction(true);
 
673
                else  document->endTransaction(false);
663
674
        }
664
 
        if (err.isSucceeded()) err=document->endTransaction(true);
665
 
        else  document->endTransaction(false);
666
675
 
667
676
        if (err.isFailed()) {
668
677
                err.addError(ERR_FAIL, tr("%1 failed").arg("SKGImportExportManager::importCSVUnit"));
678
687
        SKGTRACEL(10) << "Input filename=" << fileName << endl;
679
688
 
680
689
        //Begin transaction
681
 
        err=document->beginTransaction("#INTERNAL#", 3);
682
 
        if (err.isSucceeded()) {
683
 
                //Create account if needed
684
 
                QDateTime now=QDateTime::currentDateTime();
685
 
                QString postFix=SKGServices::dateToSqlString(now);
686
 
 
687
 
                //Default mapping
688
 
                if (getCSVMapping().count()==0) {
689
 
                        err= setCSVMapping(NULL);
690
 
                        if (err.isSucceeded()) err=document->sendMessage(tr("Use automatic CSV mapping detection"));
691
 
                }
692
 
 
693
 
                //Step 1 done
694
 
                if (err.isSucceeded()) err=document->stepForward(1);
695
 
 
696
 
                //Open file
 
690
        if (document) {
 
691
                err=document->beginTransaction("#INTERNAL#", 3);
697
692
                if (err.isSucceeded()) {
698
 
                        QFile file(fileName);
699
 
                        if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
700
 
                                err.setReturnCode(ERR_INVALIDARG);
701
 
                                err.setMessage(tr("Open file [%1] failed").arg(fileName));
702
 
                        } else {
703
 
                                QTextStream stream(&file);
704
 
                                if (!codec.isEmpty()) stream.setCodec(codec.toAscii().constData());
705
 
 
706
 
                                //Ignore useless lines
707
 
                                int headerIndex=getCSVHeaderIndex();
708
 
                                for (int i=0; i<=headerIndex; ++i)
709
 
                                        stream.readLine();
710
 
 
711
 
                                //Get data column
712
 
                                QStringList dates;
713
 
                                QStringList lines;
714
 
                                int posdate=csvMapping.indexOf("date");
715
 
                                if (posdate!=-1) {
716
 
                                        while (!stream.atEnd()) {
717
 
                                                //Read line
718
 
                                                QString line=stream.readLine().trimmed();
719
 
                                                if (!line.isEmpty()) {
720
 
                                                        lines.push_back(line);
721
 
 
722
 
                                                        //Get date
723
 
                                                        QStringList field=SKGServices::splitCSVLine(line);
724
 
                                                        if (posdate<field.count()) dates.push_back(field.at(posdate));
725
 
                                                }
726
 
                                        }
727
 
                                }
728
 
 
729
 
                                //close file
730
 
                                file.close();
731
 
 
732
 
                                //Select dateformat
733
 
                                QString dateFormat=SKGServices::getDateFormat(dates);
734
 
                                if (dateFormat.isEmpty()) {
735
 
                                        err.setReturnCode(ERR_FAIL);
736
 
                                        err.setMessage(tr("Date format not supported"));
737
 
                                }
738
 
                                if (err.isSucceeded())
739
 
                                        err=document->sendMessage(tr("Import of [%1] with code [%2] and date format [%3]").arg(fileName).arg(codec).arg(dateFormat));
740
 
 
741
 
                                //Step 2 done
742
 
                                if (err.isSucceeded()) err=document->stepForward(2);
743
 
 
744
 
                                //Treat all lines
745
 
                                if (err.isSucceeded()) {
746
 
                                        int nb=lines.size();
747
 
                                        err=document->beginTransaction("#INTERNAL#", nb);
748
 
 
749
 
                                        //Save last mapping used in a settings
750
 
                                        QString mappingDesc;
751
 
                                        int nbMap=csvMapping.count();
752
 
                                        for (int i=0; i<nbMap;++i) {
753
 
                                                if (i) mappingDesc+='|';
754
 
                                                mappingDesc+=csvMapping.at(i);
755
 
                                        }
756
 
                                        if (err.isSucceeded()) err=document->setParameter("SKG_LAST_CSV_MAPPING_USED", mappingDesc);
757
 
 
758
 
                                        SKGUnitObject defUnit;
759
 
                                        SKGAccountObject defAccount;
760
 
                                        int nbOperationsNotImported=0;
761
 
                                        for (int i = 0; err.isSucceeded() && i < nb; ++i) {
762
 
                                                SKGOperationObject currentOperation(document);
763
 
                                                SKGSubOperationObject currentSubOperation(document);
764
 
 
765
 
                                                //Valuate mandatory attribute with default value
766
 
                                                if (csvMapping.indexOf("unit")==-1) {
767
 
                                                        err=getDefaultUnit(defUnit);
768
 
                                                        if (err.isSucceeded()) err=currentOperation.setUnit(defUnit);
769
 
                                                }
770
 
                                                if (err.isSucceeded() && csvMapping.indexOf("account")==-1) {
771
 
                                                        err=getDefaultAccount(defAccount);
772
 
                                                        if (err.isSucceeded()) err=currentOperation.setParentAccount(defAccount);
773
 
                                                }
774
 
 
775
 
                                                QString line=lines.at(i);
776
 
                                                QByteArray hash = QCryptographicHash::hash(line.toUtf8(), QCryptographicHash::Md5);
777
 
 
778
 
                                                SKGObjectBase opWithThisHash;
779
 
                                                if (SKGObjectBase::getObject(document, "operation", "t_imported='Y' AND t_import_id='"+QString(hash.toHex())+'\'', opWithThisHash).isSucceeded()) nbOperationsNotImported++;
780
 
                                                else {
781
 
                                                        QStringList atts=SKGServices::splitCSVLine(line);
782
 
                                                        int nbcol=csvMapping.count();
783
 
                                                        for (int c=0; err.isSucceeded() && c<nbcol; ++c) {
784
 
                                                                QString col=csvMapping[c];
785
 
                                                                int pos=csvMapping.indexOf(col);
786
 
                                                                QString val;
787
 
                                                                if (pos!=-1) val=atts.at(pos).trimmed();
788
 
                                                                if (col=="date") {
789
 
                                                                        err=currentOperation.setDate(SKGServices::stringToTime(SKGServices::dateToSqlString(val, dateFormat)).date());
790
 
                                                                } else if (col=="number") {
791
 
                                                                        if (!val.isEmpty()) err=currentOperation.setNumber(SKGServices::stringToInt(val));
792
 
                                                                } else if (col=="mode") {
793
 
                                                                        err=currentOperation.setMode(val);
794
 
                                                                } else if (col=="payee") {
795
 
                                                                        err=currentOperation.setPayee(val);
796
 
                                                                } else if (col=="comment") {
797
 
                                                                        err=currentOperation.setComment(val);
798
 
                                                                } else if (col=="status") {
799
 
                                                                        err=currentOperation.setStatus(val=="C" ?  SKGOperationObject::CHECKED : val=="P" ?  SKGOperationObject::POINTED :SKGOperationObject::NONE);
800
 
                                                                } else if (col=="bookmarked") {
801
 
                                                                        err=currentOperation.bookmark(val=="Y");
802
 
                                                                }  else if (col=="amount" && !csvMapping.contains("quantity")) {
803
 
                                                                        err=currentSubOperation.setQuantity(SKGServices::stringToDouble(val));
804
 
                                                                }  else if (col=="quantity") {
805
 
                                                                        err=currentSubOperation.setQuantity(SKGServices::stringToDouble(val));
806
 
                                                                }  else if (col=="sign") {
807
 
                                                                        if (val=="DEBIT" || val=="-") { // krazy:exclude=doublequote_chars
808
 
                                                                                double cval=currentSubOperation.getQuantity();
809
 
                                                                                if (cval>0) err=currentSubOperation.setQuantity(-cval);
810
 
                                                                        }
811
 
                                                                } else if (col=="unit") {
812
 
                                                                        //Looking for unit
813
 
                                                                        SKGUnitObject unit(document);
814
 
                                                                        if (val!=defUnit.getName()) { //For performance
815
 
                                                                                err=unit.setName(val);
816
 
                                                                                if (err.isSucceeded()) err=unit.setSymbol(val);
817
 
                                                                                if (err.isSucceeded() && unit.load().isFailed())  err=unit.save(false); //Save only
818
 
 
819
 
                                                                                //This unit is now the default one, it's better for performance
820
 
                                                                                defUnit=unit;
821
 
                                                                        } else {
822
 
                                                                                unit=defUnit;
823
 
                                                                        }
824
 
 
825
 
                                                                        SKGUnitValueObject unitval;
826
 
                                                                        if (err.isSucceeded()) err=unit.addUnitValue(unitval);
827
 
                                                                        if (err.isSucceeded()) {
828
 
                                                                                int posAmount=csvMapping.indexOf("amount");
829
 
                                                                                int posQuantity=csvMapping.indexOf("quantity");
830
 
                                                                                if (posAmount!=-1 && posQuantity!=-1) {
831
 
                                                                                        err=unitval.setQuantity(SKGServices::stringToDouble(atts.at(posAmount))/SKGServices::stringToDouble(atts.at(posQuantity)));
 
693
                        //Create account if needed
 
694
                        QDateTime now=QDateTime::currentDateTime();
 
695
                        QString postFix=SKGServices::dateToSqlString(now);
 
696
 
 
697
                        //Default mapping
 
698
                        if (getCSVMapping().count()==0) {
 
699
                                err= setCSVMapping(NULL);
 
700
                                if (err.isSucceeded()) err=document->sendMessage(tr("Use automatic CSV mapping detection"));
 
701
                        }
 
702
 
 
703
                        //Step 1 done
 
704
                        if (err.isSucceeded()) err=document->stepForward(1);
 
705
 
 
706
                        //Open file
 
707
                        if (err.isSucceeded()) {
 
708
                                QFile file(fileName);
 
709
                                if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
 
710
                                        err.setReturnCode(ERR_INVALIDARG);
 
711
                                        err.setMessage(tr("Open file [%1] failed").arg(fileName));
 
712
                                } else {
 
713
                                        QTextStream stream(&file);
 
714
                                        if (!codec.isEmpty()) stream.setCodec(codec.toAscii().constData());
 
715
 
 
716
                                        //Ignore useless lines
 
717
                                        int headerIndex=getCSVHeaderIndex();
 
718
                                        for (int i=0; i<=headerIndex; ++i)
 
719
                                                stream.readLine();
 
720
 
 
721
                                        //Get data column
 
722
                                        QStringList dates;
 
723
                                        QStringList lines;
 
724
                                        int posdate=csvMapping.indexOf("date");
 
725
                                        if (posdate!=-1) {
 
726
                                                while (!stream.atEnd()) {
 
727
                                                        //Read line
 
728
                                                        QString line=stream.readLine().trimmed();
 
729
                                                        if (!line.isEmpty()) {
 
730
                                                                lines.push_back(line);
 
731
 
 
732
                                                                //Get date
 
733
                                                                QStringList field=SKGServices::splitCSVLine(line);
 
734
                                                                if (posdate<field.count()) dates.push_back(field.at(posdate));
 
735
                                                        }
 
736
                                                }
 
737
                                        }
 
738
 
 
739
                                        //close file
 
740
                                        file.close();
 
741
 
 
742
                                        //Select dateformat
 
743
                                        QString dateFormat=SKGServices::getDateFormat(dates);
 
744
                                        if (dateFormat.isEmpty()) {
 
745
                                                err.setReturnCode(ERR_FAIL);
 
746
                                                err.setMessage(tr("Date format not supported"));
 
747
                                        }
 
748
                                        if (err.isSucceeded())
 
749
                                                err=document->sendMessage(tr("Import of [%1] with code [%2] and date format [%3]").arg(fileName).arg(codec).arg(dateFormat));
 
750
 
 
751
                                        //Step 2 done
 
752
                                        if (err.isSucceeded()) err=document->stepForward(2);
 
753
 
 
754
                                        //Treat all lines
 
755
                                        if (err.isSucceeded()) {
 
756
                                                int nb=lines.size();
 
757
                                                err=document->beginTransaction("#INTERNAL#", nb);
 
758
 
 
759
                                                //Save last mapping used in a settings
 
760
                                                QString mappingDesc;
 
761
                                                int nbMap=csvMapping.count();
 
762
                                                for (int i=0; i<nbMap;++i) {
 
763
                                                        if (i) mappingDesc+='|';
 
764
                                                        mappingDesc+=csvMapping.at(i);
 
765
                                                }
 
766
                                                if (err.isSucceeded()) err=document->setParameter("SKG_LAST_CSV_MAPPING_USED", mappingDesc);
 
767
 
 
768
                                                SKGUnitObject defUnit;
 
769
                                                SKGAccountObject defAccount;
 
770
                                                int nbOperationsNotImported=0;
 
771
                                                for (int i = 0; err.isSucceeded() && i < nb; ++i) {
 
772
                                                        SKGOperationObject currentOperation(document);
 
773
                                                        SKGSubOperationObject currentSubOperation(document);
 
774
 
 
775
                                                        //Valuate mandatory attribute with default value
 
776
                                                        if (csvMapping.indexOf("unit")==-1) {
 
777
                                                                err=getDefaultUnit(defUnit);
 
778
                                                                if (err.isSucceeded()) err=currentOperation.setUnit(defUnit);
 
779
                                                        }
 
780
                                                        if (err.isSucceeded() && csvMapping.indexOf("account")==-1) {
 
781
                                                                err=getDefaultAccount(defAccount);
 
782
                                                                if (err.isSucceeded()) err=currentOperation.setParentAccount(defAccount);
 
783
                                                        }
 
784
 
 
785
                                                        QString line=lines.at(i);
 
786
                                                        QByteArray hash = QCryptographicHash::hash(line.toUtf8(), QCryptographicHash::Md5);
 
787
 
 
788
                                                        SKGObjectBase opWithThisHash;
 
789
                                                        if (SKGObjectBase::getObject(document, "operation", "t_imported='Y' AND t_import_id='"+QString(hash.toHex())+'\'', opWithThisHash).isSucceeded()) nbOperationsNotImported++;
 
790
                                                        else {
 
791
                                                                QStringList atts=SKGServices::splitCSVLine(line);
 
792
                                                                int nbcol=csvMapping.count();
 
793
                                                                for (int c=0; err.isSucceeded() && c<nbcol; ++c) {
 
794
                                                                        QString col=csvMapping[c];
 
795
                                                                        int pos=csvMapping.indexOf(col);
 
796
                                                                        QString val;
 
797
                                                                        if (pos!=-1) val=atts.at(pos).trimmed();
 
798
                                                                        if (col=="date") {
 
799
                                                                                err=currentOperation.setDate(SKGServices::stringToTime(SKGServices::dateToSqlString(val, dateFormat)).date());
 
800
                                                                        } else if (col=="number") {
 
801
                                                                                if (!val.isEmpty()) err=currentOperation.setNumber(SKGServices::stringToInt(val));
 
802
                                                                        } else if (col=="mode") {
 
803
                                                                                err=currentOperation.setMode(val);
 
804
                                                                        } else if (col=="payee") {
 
805
                                                                                err=currentOperation.setPayee(val);
 
806
                                                                        } else if (col=="comment") {
 
807
                                                                                err=currentOperation.setComment(val);
 
808
                                                                        } else if (col=="status") {
 
809
                                                                                err=currentOperation.setStatus(val=="C" ?  SKGOperationObject::CHECKED : val=="P" ?  SKGOperationObject::POINTED :SKGOperationObject::NONE);
 
810
                                                                        } else if (col=="bookmarked") {
 
811
                                                                                err=currentOperation.bookmark(val=="Y");
 
812
                                                                        }  else if (col=="amount" && !csvMapping.contains("quantity")) {
 
813
                                                                                err=currentSubOperation.setQuantity(SKGServices::stringToDouble(val));
 
814
                                                                        }  else if (col=="quantity") {
 
815
                                                                                err=currentSubOperation.setQuantity(SKGServices::stringToDouble(val));
 
816
                                                                        }  else if (col=="sign") {
 
817
                                                                                if (val=="DEBIT" || val=="-") { // krazy:exclude=doublequote_chars
 
818
                                                                                        double cval=currentSubOperation.getQuantity();
 
819
                                                                                        if (cval>0) err=currentSubOperation.setQuantity(-cval);
 
820
                                                                                }
 
821
                                                                        } else if (col=="unit") {
 
822
                                                                                //Looking for unit
 
823
                                                                                SKGUnitObject unit(document);
 
824
                                                                                if (val!=defUnit.getName()) { //For performance
 
825
                                                                                        err=unit.setName(val);
 
826
                                                                                        if (err.isSucceeded()) err=unit.setSymbol(val);
 
827
                                                                                        if (err.isSucceeded() && unit.load().isFailed())  err=unit.save(false); //Save only
 
828
 
 
829
                                                                                        //This unit is now the default one, it's better for performance
 
830
                                                                                        defUnit=unit;
832
831
                                                                                } else {
833
 
                                                                                        err=unitval.setQuantity(1);
834
 
                                                                                }
835
 
                                                                        }
836
 
                                                                        if (err.isSucceeded()) err=unitval.setDate(now.date());
837
 
                                                                        if (err.isSucceeded()) err=unitval.save();
838
 
                                                                        if (err.isSucceeded()) err=currentOperation.setUnit(unit);
839
 
                                                                } else if (col=="account") {
840
 
                                                                        //Looking for account
841
 
                                                                        if (val!=defAccount.getName()) { //For performance
842
 
                                                                                SKGAccountObject account(document);
843
 
                                                                                account.setName(val);
844
 
                                                                                err=account.load();
845
 
                                                                                if (err.isFailed()) {
846
 
                                                                                        //Not found, we have to create one
847
 
                                                                                        SKGBankObject bank(document);
848
 
                                                                                        QString name=tr("Bank for import %1").arg(postFix);
849
 
                                                                                        err=bank.setName(name);
850
 
                                                                                        if (err.isSucceeded() && bank.load().isFailed()) {
851
 
                                                                                                err=bank.save(false);  //Save only
852
 
                                                                                                if (err.isSucceeded()) err=document->sendMessage(tr("Default bank [%1] created for import").arg(name));
853
 
                                                                                        }
854
 
                                                                                        if (err.isSucceeded()) err=bank.addAccount(account);
855
 
                                                                                        if (err.isSucceeded()) err=account.setName(val);
856
 
                                                                                        if (err.isSucceeded() && account.load().isFailed())  err=account.save(false);  //Save only
857
 
                                                                                }
858
 
 
859
 
                                                                                //This account is now the default one, it's better for performance
860
 
                                                                                defAccount=account;
861
 
                                                                        }
862
 
                                                                        if (err.isSucceeded()) err=currentOperation.setParentAccount(defAccount);
863
 
                                                                } else if (col=="category") {
864
 
                                                                        //Set Category
865
 
                                                                        if (!val.isEmpty()) {
866
 
                                                                                SKGCategoryObject Category;
867
 
                                                                                val.replace('/', OBJECTSEPARATOR);
868
 
                                                                                val.replace(':', OBJECTSEPARATOR);
869
 
                                                                                val.replace(',', OBJECTSEPARATOR);
870
 
                                                                                val.replace(';', OBJECTSEPARATOR);
871
 
                                                                                err=SKGCategoryObject::createPathCategory(document,val, Category);
872
 
                                                                                if (err.isSucceeded())  err=currentSubOperation.setCategory(Category);
873
 
                                                                        }
 
832
                                                                                        unit=defUnit;
 
833
                                                                                }
 
834
 
 
835
                                                                                SKGUnitValueObject unitval;
 
836
                                                                                if (err.isSucceeded()) err=unit.addUnitValue(unitval);
 
837
                                                                                if (err.isSucceeded()) {
 
838
                                                                                        int posAmount=csvMapping.indexOf("amount");
 
839
                                                                                        int posQuantity=csvMapping.indexOf("quantity");
 
840
                                                                                        if (posAmount!=-1 && posQuantity!=-1) {
 
841
                                                                                                err=unitval.setQuantity(SKGServices::stringToDouble(atts.at(posAmount))/SKGServices::stringToDouble(atts.at(posQuantity)));
 
842
                                                                                        } else {
 
843
                                                                                                err=unitval.setQuantity(1);
 
844
                                                                                        }
 
845
                                                                                }
 
846
                                                                                if (err.isSucceeded()) err=unitval.setDate(now.date());
 
847
                                                                                if (err.isSucceeded()) err=unitval.save();
 
848
                                                                                if (err.isSucceeded()) err=currentOperation.setUnit(unit);
 
849
                                                                        } else if (col=="account") {
 
850
                                                                                //Looking for account
 
851
                                                                                if (val!=defAccount.getName()) { //For performance
 
852
                                                                                        SKGAccountObject account(document);
 
853
                                                                                        account.setName(val);
 
854
                                                                                        err=account.load();
 
855
                                                                                        if (err.isFailed()) {
 
856
                                                                                                //Not found, we have to create one
 
857
                                                                                                SKGBankObject bank(document);
 
858
                                                                                                QString name=tr("Bank for import %1").arg(postFix);
 
859
                                                                                                err=bank.setName(name);
 
860
                                                                                                if (err.isSucceeded() && bank.load().isFailed()) {
 
861
                                                                                                        err=bank.save(false);  //Save only
 
862
                                                                                                        if (err.isSucceeded()) err=document->sendMessage(tr("Default bank [%1] created for import").arg(name));
 
863
                                                                                                }
 
864
                                                                                                if (err.isSucceeded()) err=bank.addAccount(account);
 
865
                                                                                                if (err.isSucceeded()) err=account.setName(val);
 
866
                                                                                                if (err.isSucceeded() && account.load().isFailed())  err=account.save(false);  //Save only
 
867
                                                                                        }
 
868
 
 
869
                                                                                        //This account is now the default one, it's better for performance
 
870
                                                                                        defAccount=account;
 
871
                                                                                }
 
872
                                                                                if (err.isSucceeded()) err=currentOperation.setParentAccount(defAccount);
 
873
                                                                        } else if (col=="category") {
 
874
                                                                                //Set Category
 
875
                                                                                if (!val.isEmpty()) {
 
876
                                                                                        SKGCategoryObject Category;
 
877
                                                                                        val.replace('/', OBJECTSEPARATOR);
 
878
                                                                                        val.replace(':', OBJECTSEPARATOR);
 
879
                                                                                        val.replace(',', OBJECTSEPARATOR);
 
880
                                                                                        val.replace(';', OBJECTSEPARATOR);
 
881
                                                                                        err=SKGCategoryObject::createPathCategory(document,val, Category);
 
882
                                                                                        if (err.isSucceeded())  err=currentSubOperation.setCategory(Category);
 
883
                                                                                }
 
884
                                                                        }
 
885
 
874
886
                                                                }
875
887
 
 
888
                                                                if (err.isSucceeded()) err=currentOperation.setAttribute("t_imported", "P");
 
889
                                                                if (err.isSucceeded()) err=currentOperation.setImportID(hash.toHex());
 
890
 
 
891
                                                                if (err.isSucceeded()) err=currentOperation.save(false);  //Save only
 
892
                                                                if (err.isSucceeded()) err=currentSubOperation.setParentOperation(currentOperation);
 
893
                                                                if (err.isSucceeded()) err=currentSubOperation.save(false, false);  //Save only without reload
876
894
                                                        }
877
 
 
878
 
                                                        if (err.isSucceeded()) err=currentOperation.setAttribute("t_imported", "P");
879
 
                                                        if (err.isSucceeded()) err=currentOperation.setImportID(hash.toHex());
880
 
 
881
 
                                                        if (err.isSucceeded()) err=currentOperation.save(false);  //Save only
882
 
                                                        if (err.isSucceeded()) err=currentSubOperation.setParentOperation(currentOperation);
883
 
                                                        if (err.isSucceeded()) err=currentSubOperation.save(false, false);  //Save only without reload
 
895
                                                        if (err.isSucceeded() && i%20==0) err = SKGServices::executeSqliteOrder(document, "ANALYZE");
 
896
                                                        if (err.isSucceeded()) err=document->stepForward(i+1);
884
897
                                                }
885
 
                                                if (err.isSucceeded() && i%20==0) err = SKGServices::executeSqliteOrder(document, "ANALYZE");
886
 
                                                if (err.isSucceeded()) err=document->stepForward(i+1);
 
898
                                                if (err.isSucceeded()) err = SKGServices::executeSqliteOrder(document, "UPDATE operation SET t_imported='Y' WHERE t_imported='P'");
 
899
 
 
900
                                                if (err.isSucceeded()) err=document->endTransaction(true);
 
901
                                                else  document->endTransaction(false);
 
902
 
 
903
                                                if (err.isSucceeded() && nbOperationsNotImported)
 
904
                                                        err=document->sendMessage(tr("%1 operation(s) not imported because already existing").arg(nbOperationsNotImported));
 
905
 
 
906
                                                //Lines treated
 
907
                                                if (err.isSucceeded()) err=document->stepForward(3);
887
908
                                        }
888
 
                                        if (err.isSucceeded()) err = SKGServices::executeSqliteOrder(document, "UPDATE operation SET t_imported='Y' WHERE t_imported='P'");
889
 
 
890
 
                                        if (err.isSucceeded()) err=document->endTransaction(true);
891
 
                                        else  document->endTransaction(false);
892
 
 
893
 
                                        if (err.isSucceeded() && nbOperationsNotImported)
894
 
                                                err=document->sendMessage(tr("%1 operation(s) not imported because already existing").arg(nbOperationsNotImported));
895
 
 
896
 
                                        //Lines treated
897
 
                                        if (err.isSucceeded()) err=document->stepForward(3);
898
909
                                }
899
910
                        }
900
911
                }
 
912
                if (err.isSucceeded()) err=document->endTransaction(true);
 
913
                else  document->endTransaction(false);
901
914
        }
902
 
        if (err.isSucceeded()) err=document->endTransaction(true);
903
 
        else  document->endTransaction(false);
904
915
 
905
916
        if (err.isFailed()) {
906
917
                err.addError(ERR_FAIL, tr("%1 failed").arg("SKGImportExportManager::importCSV"));
915
926
        SKGTRACEINRC(2, "SKGDocumentBank::importOFX", err);
916
927
        SKGTRACEL(10) << "Input filename=" << fileName << endl;
917
928
 
918
 
        err=document->beginTransaction("#INTERNAL#");
919
 
        if (err.isSucceeded()) {
920
 
                SKGImportExportManager::nbOperationsNotImported=0;
921
 
                SKGImportExportManager::nbOperationsImported=0;
922
 
                SKGImportExportManager::ofxError=SKGError();
923
 
 
924
 
                LibofxContextPtr ctx = libofx_get_new_context();
925
 
 
926
 
                ofx_set_transaction_cb(ctx, ofxTransactionCallback, this);
927
 
                //ofx_set_statement_cb(ctx, ofxStatementCallback, this);
928
 
                ofx_set_account_cb(ctx, ofxAccountCallback, this);
929
 
                //ofx_set_security_cb(ctx, ofxSecurityCallback, this);
930
 
                int rc=libofx_proc_file(ctx, fileName.toLatin1(), AUTODETECT);
931
 
                if (rc)  err=SKGError(ERR_FAIL, tr("Import OFX file [%1] failed").arg(fileName));
932
 
                if (err.isSucceeded()) err=SKGImportExportManager::ofxError;
933
 
 
934
 
                if (err.isSucceeded()) err=document->endTransaction(true);
935
 
                else  document->endTransaction(false);
936
 
 
937
 
                if (err.isSucceeded() && SKGImportExportManager::nbOperationsNotImported)
938
 
                        err=document->sendMessage(tr("%1 operation(s) not imported because already existing").arg(SKGImportExportManager::nbOperationsNotImported));
 
929
        if (document) {
 
930
                err=document->beginTransaction("#INTERNAL#");
 
931
                if (err.isSucceeded()) {
 
932
                        SKGImportExportManager::nbOperationsNotImported=0;
 
933
                        SKGImportExportManager::nbOperationsImported=0;
 
934
                        SKGImportExportManager::ofxError=SKGError();
 
935
 
 
936
                        LibofxContextPtr ctx = libofx_get_new_context();
 
937
 
 
938
                        ofx_set_transaction_cb(ctx, ofxTransactionCallback, this);
 
939
                        //ofx_set_statement_cb(ctx, ofxStatementCallback, this);
 
940
                        ofx_set_account_cb(ctx, ofxAccountCallback, this);
 
941
                        //ofx_set_security_cb(ctx, ofxSecurityCallback, this);
 
942
                        int rc=libofx_proc_file(ctx, fileName.toLatin1(), AUTODETECT);
 
943
                        if (rc)  err=SKGError(ERR_FAIL, tr("Import OFX file [%1] failed").arg(fileName));
 
944
                        if (err.isSucceeded()) err=SKGImportExportManager::ofxError;
 
945
 
 
946
                        if (err.isSucceeded()) err=document->endTransaction(true);
 
947
                        else  document->endTransaction(false);
 
948
 
 
949
                        if (err.isSucceeded() && SKGImportExportManager::nbOperationsNotImported)
 
950
                                err=document->sendMessage(tr("%1 operation(s) not imported because already existing").arg(SKGImportExportManager::nbOperationsNotImported));
 
951
                }
939
952
        }
940
 
 
941
953
        return err;
942
954
}
943
955
 
947
959
        if (SKGImportExportManager::ofxError.isFailed()) return 0;
948
960
 
949
961
        SKGImportExportManager* impotExporter=(SKGImportExportManager*) pv;
 
962
        if (!impotExporter) return 0;
950
963
        SKGDocumentBank* doc = impotExporter->getDocument();
 
964
        if (!doc) return 0;
951
965
 
952
966
        SKGObjectBase tmp;
953
967
        if (data.account_id_valid==true) {
1053
1067
        if (SKGImportExportManager::ofxError.isFailed()) return 0;
1054
1068
 
1055
1069
        SKGImportExportManager* impotExporter=(SKGImportExportManager*) pv;
 
1070
        if (!impotExporter) return 0;
1056
1071
        SKGDocumentBank* doc = impotExporter->getDocument();
 
1072
        if (!doc) return 0;
1057
1073
 
1058
1074
        //Get account
1059
1075
        SKGAccountObject account;
1246
1262
        //http://web.intuit.com/support/quicken/docs/d_qif.html
1247
1263
 
1248
1264
        //Begin transaction
1249
 
        err=document->beginTransaction("#INTERNAL#", 3);
1250
 
        if (err.isSucceeded()) {
1251
 
                //Create account if needed
1252
 
                QDateTime now=QDateTime::currentDateTime();
1253
 
                QString postFix=SKGServices::dateToSqlString(now);
1254
 
 
1255
 
                //Step 1 done
1256
 
                if (err.isSucceeded()) err=document->stepForward(1);
1257
 
 
1258
 
                //Open file
1259
 
                QFile file(fileName);
1260
 
                if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
1261
 
                        err.setReturnCode(ERR_INVALIDARG);
1262
 
                        err.setMessage(tr("Open file [%1] failed").arg(fileName));
1263
 
                } else {
1264
 
                        QTextStream stream(&file);
1265
 
                        if (!codec.isEmpty()) stream.setCodec(codec.toAscii().constData());
1266
 
 
1267
 
                        //load file in memory
1268
 
                        QStringList lines;
1269
 
                        QStringList dates;
1270
 
                        bool inAccountSection=false;
1271
 
                        while (!stream.atEnd()) {
1272
 
                                //Read line
1273
 
                                //Check line if line is empty or is a commented
1274
 
                                QString line=stream.readLine().trimmed();
1275
 
                                if (line.length()>0 && line[0]!='#') {
1276
 
                                        lines.push_back(line);
1277
 
                                        //Manage !Account section
1278
 
                                        if (line=="^" && inAccountSection) {
1279
 
                                                inAccountSection=false;
1280
 
                                        } else if (QString::compare(line, "!account", Qt::CaseInsensitive)==0) {
1281
 
                                                inAccountSection=true;
1282
 
                                        }
1283
 
 
1284
 
                                        //We try to find automatically the date format
1285
 
                                        else if (!inAccountSection &&line[0]=='D') {
1286
 
                                                dates.push_back(line.right(line.length()-1));
1287
 
                                        }
1288
 
                                }
1289
 
                        }
1290
 
 
1291
 
                        //close file
1292
 
                        file.close();
1293
 
 
1294
 
                        //Select dateformat
1295
 
                        QString dateFormat=SKGServices::getDateFormat(dates);
1296
 
                        if (dateFormat.isEmpty()) {
1297
 
                                err.setReturnCode(ERR_FAIL);
1298
 
                                err.setMessage(tr("Date format not supported"));
1299
 
                        }
1300
 
                        if (err.isSucceeded())
1301
 
                                err=document->sendMessage(tr("Import of [%1] with code [%2] and date format [%3]").arg(fileName).arg(codec).arg(dateFormat));
1302
 
 
1303
 
                        //Step 2 done
1304
 
                        if (err.isSucceeded()) err=document->stepForward(2);
1305
 
 
1306
 
                        //Treat all lines
1307
 
                        if (err.isSucceeded()) {
1308
 
                                SKGOperationObject currentOperation;
1309
 
                                SKGSubOperationObject currentSubOperation;
1310
 
                                QDate currentOperationDate;
1311
 
                                bool latestSubCatMustBeRemoved=false;
1312
 
                                QChar inSection='B';
1313
 
                                bool investmentAccount=false;
1314
 
                                int quantityFactor=1;
1315
 
                                QString currentUnitForInvestment;
1316
 
                                int nbOperationsNotImported=0;
1317
 
                                double currentUnitPrice=1;
1318
 
 
1319
 
                                int nb=lines.size();
1320
 
                                err=document->beginTransaction("#INTERNAL#", nb);
1321
 
                                SKGAccountObject* account=NULL;
1322
 
                                QString stringForHash;
1323
 
                                for (int i = 0; err.isSucceeded() && i < nb; ++i) {
1324
 
                                        QString line=lines.at(i);
1325
 
                                        QString val;
1326
 
                                        QChar op=line[0];
1327
 
                                        if (line.length()>1) {
1328
 
                                                val=line.right(line.length()-1).trimmed();
1329
 
                                        }
1330
 
 
1331
 
                                        //Manage !Account section
1332
 
                                        if (QString::compare(line, "!type:bank", Qt::CaseInsensitive)==0 ||
1333
 
                                                        QString::compare(line, "!type:cash", Qt::CaseInsensitive)==0 ||
1334
 
                                                        QString::compare(line, "!type:ccash", Qt::CaseInsensitive)==0 ||
1335
 
                                                        QString::compare(line, "!type:ccard", Qt::CaseInsensitive)==0 ||
1336
 
                                                        QString::compare(line, "!type:oth a", Qt::CaseInsensitive)==0 ||
1337
 
                                                        QString::compare(line, "!type:invst", Qt::CaseInsensitive)==0) {
1338
 
                                                inSection='B';
1339
 
                                                investmentAccount=(QString::compare(val, "type:invst", Qt::CaseInsensitive)==0);
1340
 
                                        } else if (QString::compare(line, "!account", Qt::CaseInsensitive)==0) {
1341
 
                                                inSection='A';
1342
 
                                        } else if (QString::compare(line, "!type:cat", Qt::CaseInsensitive)==0) {
1343
 
                                                inSection='C';
1344
 
                                                if (err.isSucceeded()) err=document->sendMessage(tr("Categories found and imported"));
1345
 
                                        } else if (line.at(0)=='!') {
1346
 
                                                inSection='?';
1347
 
                                        } else if (inSection=='C') {
1348
 
                                                //Category creation
1349
 
                                                if (op=='N') {
1350
 
                                                        SKGCategoryObject Category;
1351
 
                                                        val.replace('/', OBJECTSEPARATOR);
1352
 
                                                        val.replace(':', OBJECTSEPARATOR);
1353
 
                                                        val.replace(',', OBJECTSEPARATOR);
1354
 
                                                        val.replace(';', OBJECTSEPARATOR);
1355
 
                                                        err=SKGCategoryObject::createPathCategory(document,val, Category);
1356
 
                                                }
1357
 
                                        } else if (inSection=='A') {
1358
 
                                                //Account creation
1359
 
                                                if (op=='N') {
1360
 
                                                        //Check if the account already exist
1361
 
                                                        SKGAccountObject account2;
1362
 
                                                        err=SKGNamedObject::getObjectByName(document, "account", val, account2);
1363
 
                                                        if (err.isFailed()) {
1364
 
                                                                //Create account
1365
 
                                                                SKGBankObject bank(document);
1366
 
                                                                err=bank.setName(tr("Bank for import %1").arg(postFix));
1367
 
                                                                if (err.isSucceeded() && bank.load().isFailed()) err=bank.save(false);
1368
 
                                                                if (err.isSucceeded()) err=bank.addAccount(account2);
1369
 
                                                                if (err.isSucceeded()) err=account2.setName(val);
1370
 
                                                                if (err.isSucceeded() && account2.load().isFailed()) err=account2.save(false);  //Save only
1371
 
                                                        }
1372
 
 
1373
 
                                                        if (err.isSucceeded()) {
1374
 
                                                                if (account) {
1375
 
                                                                        delete account;
1376
 
                                                                        account=NULL;
1377
 
                                                                }
1378
 
                                                                account=new SKGAccountObject(account2);
1379
 
                                                        }
1380
 
                                                } else if (op=='D') {
1381
 
                                                        if (account) err=account->setNumber(val);
1382
 
                                                } else if (op=='^') {
1383
 
                                                        //^     End of entry
1384
 
                                                        //save
1385
 
                                                        if (account) err=account->save();
1386
 
                                                }
1387
 
                                        } else if (inSection=='B') {
1388
 
                                                //Operation creation
1389
 
                                                /*
1390
 
                                                >>>> Items for Non-Investment Accounts <<<<
1391
 
                                                DONE    D      Date
1392
 
                                                DONE    T      Amount
1393
 
                                                        U      Transaction amount (higher possible value than T)
1394
 
                                                DONE    C      Cleared status
1395
 
                                                DONE    N      Number (check or reference number)
1396
 
                                                DONE    P      Payee/description
1397
 
                                                DONE    M      Memo
1398
 
                                                        A      Address (up to 5 lines; 6th line is an optional message)
1399
 
                                                DONE    L      Category (category/class or transfer/class)
1400
 
                                                DONE    S      Category in split (category/class or transfer/class)
1401
 
                                                        E      Memo in split
1402
 
                                                DONE    $      Dollar amount of split
1403
 
                                                TODO    %      Percentage of split if percentages are used
1404
 
                                                        F      Reimbursable business expense flag
1405
 
                                                        X      Small Business extensions
1406
 
                                                DONE    ^      End of entry
1407
 
 
1408
 
                                                >>>> Items for Investment Accounts <<<<
1409
 
                                                DONE    D       Date
1410
 
                                                        N       Action
1411
 
                                                DONE    Y       Security
1412
 
                                                DONE    I       Price
1413
 
                                                DONE    Q       Quantity (number of shares or split ratio)
1414
 
                                                DONE    T       Transaction amount
1415
 
                                                DONE    C       Cleared status
1416
 
                                                        P       Text in the first line for transfers and reminders
1417
 
                                                DONE    M       Memo
1418
 
                                                        O       Commission
1419
 
                                                        L       Account for the transfer
1420
 
                                                        $       Amount transferred
1421
 
                                                        ^       End of entry
1422
 
                                                */
1423
 
                                                stringForHash+=line;
1424
 
                                                if (op=='D') {
1425
 
                                                        //D     Date
 
1265
        if (document) {
 
1266
                err=document->beginTransaction("#INTERNAL#", 3);
 
1267
                if (err.isSucceeded()) {
 
1268
                        //Create account if needed
 
1269
                        QDateTime now=QDateTime::currentDateTime();
 
1270
                        QString postFix=SKGServices::dateToSqlString(now);
 
1271
 
 
1272
                        //Step 1 done
 
1273
                        if (err.isSucceeded()) err=document->stepForward(1);
 
1274
 
 
1275
                        //Open file
 
1276
                        QFile file(fileName);
 
1277
                        if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
 
1278
                                err.setReturnCode(ERR_INVALIDARG);
 
1279
                                err.setMessage(tr("Open file [%1] failed").arg(fileName));
 
1280
                        } else {
 
1281
                                QTextStream stream(&file);
 
1282
                                if (!codec.isEmpty()) stream.setCodec(codec.toAscii().constData());
 
1283
 
 
1284
                                //load file in memory
 
1285
                                QStringList lines;
 
1286
                                QStringList dates;
 
1287
                                bool inAccountSection=false;
 
1288
                                while (!stream.atEnd()) {
 
1289
                                        //Read line
 
1290
                                        //Check line if line is empty or is a commented
 
1291
                                        QString line=stream.readLine().trimmed();
 
1292
                                        if (line.length()>0 && line[0]!='#') {
 
1293
                                                lines.push_back(line);
 
1294
                                                //Manage !Account section
 
1295
                                                if (line=="^" && inAccountSection) {
 
1296
                                                        inAccountSection=false;
 
1297
                                                } else if (QString::compare(line, "!account", Qt::CaseInsensitive)==0) {
 
1298
                                                        inAccountSection=true;
 
1299
                                                }
 
1300
 
 
1301
                                                //We try to find automatically the date format
 
1302
                                                else if (!inAccountSection &&line[0]=='D') {
 
1303
                                                        dates.push_back(line.right(line.length()-1));
 
1304
                                                }
 
1305
                                        }
 
1306
                                }
 
1307
 
 
1308
                                //close file
 
1309
                                file.close();
 
1310
 
 
1311
                                //Select dateformat
 
1312
                                QString dateFormat=SKGServices::getDateFormat(dates);
 
1313
                                if (dateFormat.isEmpty()) {
 
1314
                                        err.setReturnCode(ERR_FAIL);
 
1315
                                        err.setMessage(tr("Date format not supported"));
 
1316
                                }
 
1317
                                if (err.isSucceeded())
 
1318
                                        err=document->sendMessage(tr("Import of [%1] with code [%2] and date format [%3]").arg(fileName).arg(codec).arg(dateFormat));
 
1319
 
 
1320
                                //Step 2 done
 
1321
                                if (err.isSucceeded()) err=document->stepForward(2);
 
1322
 
 
1323
                                //Treat all lines
 
1324
                                if (err.isSucceeded()) {
 
1325
                                        SKGOperationObject currentOperation;
 
1326
                                        SKGSubOperationObject currentSubOperation;
 
1327
                                        QDate currentOperationDate;
 
1328
                                        bool latestSubCatMustBeRemoved=false;
 
1329
                                        QChar inSection='B';
 
1330
                                        bool investmentAccount=false;
 
1331
                                        int quantityFactor=1;
 
1332
                                        QString currentUnitForInvestment;
 
1333
                                        int nbOperationsNotImported=0;
 
1334
                                        double currentUnitPrice=1;
 
1335
 
 
1336
                                        int nb=lines.size();
 
1337
                                        err=document->beginTransaction("#INTERNAL#", nb);
 
1338
                                        SKGAccountObject* account=NULL;
 
1339
                                        QString stringForHash;
 
1340
                                        for (int i = 0; err.isSucceeded() && i < nb; ++i) {
 
1341
                                                QString line=lines.at(i);
 
1342
                                                QString val;
 
1343
                                                QChar op=line[0];
 
1344
                                                if (line.length()>1) {
 
1345
                                                        val=line.right(line.length()-1).trimmed();
 
1346
                                                }
 
1347
 
 
1348
                                                //Manage !Account section
 
1349
                                                if (QString::compare(line, "!type:bank", Qt::CaseInsensitive)==0 ||
 
1350
                                                                QString::compare(line, "!type:cash", Qt::CaseInsensitive)==0 ||
 
1351
                                                                QString::compare(line, "!type:ccash", Qt::CaseInsensitive)==0 ||
 
1352
                                                                QString::compare(line, "!type:ccard", Qt::CaseInsensitive)==0 ||
 
1353
                                                                QString::compare(line, "!type:oth a", Qt::CaseInsensitive)==0 ||
 
1354
                                                                QString::compare(line, "!type:invst", Qt::CaseInsensitive)==0) {
 
1355
                                                        inSection='B';
 
1356
                                                        investmentAccount=(QString::compare(val, "type:invst", Qt::CaseInsensitive)==0);
 
1357
                                                } else if (QString::compare(line, "!account", Qt::CaseInsensitive)==0) {
 
1358
                                                        inSection='A';
 
1359
                                                } else if (QString::compare(line, "!type:cat", Qt::CaseInsensitive)==0) {
 
1360
                                                        inSection='C';
 
1361
                                                        if (err.isSucceeded()) err=document->sendMessage(tr("Categories found and imported"));
 
1362
                                                } else if (line.at(0)=='!') {
 
1363
                                                        inSection='?';
 
1364
                                                } else if (inSection=='C') {
 
1365
                                                        //Category creation
 
1366
                                                        if (op=='N') {
 
1367
                                                                SKGCategoryObject Category;
 
1368
                                                                val.replace('/', OBJECTSEPARATOR);
 
1369
                                                                val.replace(':', OBJECTSEPARATOR);
 
1370
                                                                val.replace(',', OBJECTSEPARATOR);
 
1371
                                                                val.replace(';', OBJECTSEPARATOR);
 
1372
                                                                err=SKGCategoryObject::createPathCategory(document,val, Category);
 
1373
                                                        }
 
1374
                                                } else if (inSection=='A') {
 
1375
                                                        //Account creation
 
1376
                                                        if (op=='N') {
 
1377
                                                                //Check if the account already exist
 
1378
                                                                SKGAccountObject account2;
 
1379
                                                                err=SKGNamedObject::getObjectByName(document, "account", val, account2);
 
1380
                                                                if (err.isFailed()) {
 
1381
                                                                        //Create account
 
1382
                                                                        SKGBankObject bank(document);
 
1383
                                                                        err=bank.setName(tr("Bank for import %1").arg(postFix));
 
1384
                                                                        if (err.isSucceeded() && bank.load().isFailed()) err=bank.save(false);
 
1385
                                                                        if (err.isSucceeded()) err=bank.addAccount(account2);
 
1386
                                                                        if (err.isSucceeded()) err=account2.setName(val);
 
1387
                                                                        if (err.isSucceeded() && account2.load().isFailed()) err=account2.save(false);  //Save only
 
1388
                                                                }
 
1389
 
 
1390
                                                                if (err.isSucceeded()) {
 
1391
                                                                        if (account) {
 
1392
                                                                                delete account;
 
1393
                                                                                account=NULL;
 
1394
                                                                        }
 
1395
                                                                        account=new SKGAccountObject(account2);
 
1396
                                                                }
 
1397
                                                        } else if (op=='D') {
 
1398
                                                                if (account) err=account->setNumber(val);
 
1399
                                                        } else if (op=='^') {
 
1400
                                                                //^     End of entry
 
1401
                                                                //save
 
1402
                                                                if (account) err=account->save();
 
1403
                                                        }
 
1404
                                                } else if (inSection=='B') {
 
1405
                                                        //Operation creation
1426
1406
                                                        /*
1427
 
                                                        Dates in US QIF files are usually in the format MM/DD/YY, although
1428
 
                                                        four-digit years are not uncommon.  Dates sometimes occur without the
1429
 
                                                        slash separator, or using other separators in place of the slash,
1430
 
                                                        commonly '-' and '.'.  US Quicken seems to be using the ' to indicate
1431
 
                                                        post-2000 two-digit years (such as 01/01'00 for Jan 1 2000).  Some
1432
 
                                                        banks appear to be using a completely undifferentiated numeric QString
1433
 
                                                        formateed YYYYMMDD in downloaded QIF files.
 
1407
                                                        >>>> Items for Non-Investment Accounts <<<<
 
1408
                                                        DONE    D      Date
 
1409
                                                        DONE    T      Amount
 
1410
                                                                U      Transaction amount (higher possible value than T)
 
1411
                                                        DONE    C      Cleared status
 
1412
                                                        DONE    N      Number (check or reference number)
 
1413
                                                        DONE    P      Payee/description
 
1414
                                                        DONE    M      Memo
 
1415
                                                                A      Address (up to 5 lines; 6th line is an optional message)
 
1416
                                                        DONE    L      Category (category/class or transfer/class)
 
1417
                                                        DONE    S      Category in split (category/class or transfer/class)
 
1418
                                                                E      Memo in split
 
1419
                                                        DONE    $      Dollar amount of split
 
1420
                                                        TODO    %      Percentage of split if percentages are used
 
1421
                                                                F      Reimbursable business expense flag
 
1422
                                                                X      Small Business extensions
 
1423
                                                        DONE    ^      End of entry
 
1424
 
 
1425
                                                        >>>> Items for Investment Accounts <<<<
 
1426
                                                        DONE    D       Date
 
1427
                                                                N       Action
 
1428
                                                        DONE    Y       Security
 
1429
                                                        DONE    I       Price
 
1430
                                                        DONE    Q       Quantity (number of shares or split ratio)
 
1431
                                                        DONE    T       Transaction amount
 
1432
                                                        DONE    C       Cleared status
 
1433
                                                                P       Text in the first line for transfers and reminders
 
1434
                                                        DONE    M       Memo
 
1435
                                                                O       Commission
 
1436
                                                                L       Account for the transfer
 
1437
                                                                $       Amount transferred
 
1438
                                                                ^       End of entry
1434
1439
                                                        */
1435
 
                                                        //Operation creation
1436
 
                                                        if (err.isSucceeded()) {
1437
 
                                                                if (account!=NULL) err=account->addOperation(currentOperation);
 
1440
                                                        stringForHash+=line;
 
1441
                                                        if (op=='D') {
 
1442
                                                                //D     Date
 
1443
                                                                /*
 
1444
                                                                Dates in US QIF files are usually in the format MM/DD/YY, although
 
1445
                                                                four-digit years are not uncommon.  Dates sometimes occur without the
 
1446
                                                                slash separator, or using other separators in place of the slash,
 
1447
                                                                commonly '-' and '.'.  US Quicken seems to be using the ' to indicate
 
1448
                                                                post-2000 two-digit years (such as 01/01'00 for Jan 1 2000).  Some
 
1449
                                                                banks appear to be using a completely undifferentiated numeric QString
 
1450
                                                                formateed YYYYMMDD in downloaded QIF files.
 
1451
                                                                */
 
1452
                                                                //Operation creation
 
1453
                                                                if (err.isSucceeded()) {
 
1454
                                                                        if (account!=NULL) err=account->addOperation(currentOperation);
 
1455
                                                                        else {
 
1456
                                                                                SKGAccountObject defAccount;
 
1457
                                                                                err=getDefaultAccount(defAccount);
 
1458
                                                                                if (err.isSucceeded()) err=defAccount.addOperation(currentOperation);
 
1459
                                                                        }
 
1460
                                                                }
 
1461
 
 
1462
                                                                //Set date
 
1463
                                                                currentOperationDate=SKGServices::stringToTime(SKGServices::dateToSqlString(val, dateFormat)).date();
 
1464
                                                                if (err.isSucceeded()) err=currentOperation.setDate(currentOperationDate);
 
1465
 
 
1466
                                                                //Set unit
 
1467
                                                                if (err.isSucceeded()) {
 
1468
                                                                        //Create unit if needed
 
1469
                                                                        SKGUnitObject unit;
 
1470
                                                                        err=getDefaultUnit(unit, &currentOperationDate);
 
1471
                                                                        if (err.isSucceeded())  err=currentOperation.setUnit(unit);
 
1472
                                                                }
 
1473
 
 
1474
                                                                if (err.isSucceeded()) currentOperation.save();
 
1475
 
 
1476
                                                                //Create suboperation
 
1477
                                                                if (err.isSucceeded()) err=currentOperation.addSubOperation(currentSubOperation);
 
1478
                                                        } else if (op=='Y') {
 
1479
                                                                //Y     Security
 
1480
                                                                currentUnitForInvestment=val;
 
1481
 
 
1482
                                                                SKGUnitObject unit(document);
 
1483
                                                                err = unit.setName(currentUnitForInvestment);
 
1484
                                                                if (unit.load().isFailed()) {
 
1485
                                                                        if (err.isSucceeded()) err = unit.setSymbol(currentUnitForInvestment);
 
1486
                                                                        if (err.isSucceeded()) err = unit.setType(SKGUnitObject::SHARE);
 
1487
                                                                        if (err.isSucceeded()) err = unit.save(false);  //Save only
 
1488
                                                                }
 
1489
                                                                if (err.isSucceeded()) err=currentOperation.setUnit(unit);
 
1490
                                                        } else if (op=='O') {
 
1491
                                                                //O     Commission
 
1492
                                                                SKGOperationObject commission;
 
1493
                                                                if (account!=NULL) err=account->addOperation(commission);
1438
1494
                                                                else {
1439
1495
                                                                        SKGAccountObject defAccount;
1440
1496
                                                                        err=getDefaultAccount(defAccount);
1441
 
                                                                        if (err.isSucceeded()) err=defAccount.addOperation(currentOperation);
1442
 
                                                                }
1443
 
                                                        }
1444
 
 
1445
 
                                                        //Set date
1446
 
                                                        currentOperationDate=SKGServices::stringToTime(SKGServices::dateToSqlString(val, dateFormat)).date();
1447
 
                                                        if (err.isSucceeded()) err=currentOperation.setDate(currentOperationDate);
1448
 
 
1449
 
                                                        //Set unit
1450
 
                                                        if (err.isSucceeded()) {
1451
 
                                                                //Create unit if needed
1452
 
                                                                SKGUnitObject unit;
1453
 
                                                                err=getDefaultUnit(unit, &currentOperationDate);
1454
 
                                                                if (err.isSucceeded())  err=currentOperation.setUnit(unit);
1455
 
                                                        }
1456
 
 
1457
 
                                                        if (err.isSucceeded()) currentOperation.save();
1458
 
 
1459
 
                                                        //Create suboperation
1460
 
                                                        if (err.isSucceeded()) err=currentOperation.addSubOperation(currentSubOperation);
1461
 
                                                } else if (op=='Y') {
1462
 
                                                        //Y     Security
1463
 
                                                        currentUnitForInvestment=val;
1464
 
 
1465
 
                                                        SKGUnitObject unit(document);
1466
 
                                                        err = unit.setName(currentUnitForInvestment);
1467
 
                                                        if (unit.load().isFailed()) {
1468
 
                                                                if (err.isSucceeded()) err = unit.setSymbol(currentUnitForInvestment);
1469
 
                                                                if (err.isSucceeded()) err = unit.setType(SKGUnitObject::SHARE);
1470
 
                                                                if (err.isSucceeded()) err = unit.save(false);  //Save only
1471
 
                                                        }
1472
 
                                                        if (err.isSucceeded()) err=currentOperation.setUnit(unit);
1473
 
                                                } else if (op=='O') {
1474
 
                                                        //O     Commission
1475
 
                                                        SKGOperationObject commission;
1476
 
                                                        if (account!=NULL) err=account->addOperation(commission);
1477
 
                                                        else {
1478
 
                                                                SKGAccountObject defAccount;
1479
 
                                                                err=getDefaultAccount(defAccount);
1480
 
                                                                if (err.isSucceeded()) err=defAccount.addOperation(commission);
1481
 
                                                        }
1482
 
                                                        if (err.isSucceeded()) err=commission.setDate(currentOperationDate);
1483
 
                                                        if (err.isSucceeded()) err=commission.setAttribute("t_imported", "P");
1484
 
                                                        if (err.isSucceeded()) {
1485
 
                                                                //Create unit if needed
1486
 
                                                                SKGUnitObject unit;
1487
 
                                                                err=getDefaultUnit(unit, &currentOperationDate);
1488
 
                                                                if (err.isSucceeded())  err=commission.setUnit(unit);
1489
 
                                                        }
1490
 
                                                        if (err.isSucceeded()) err=commission.save();  //Save only
1491
 
                                                        if (err.isSucceeded()) err=currentOperation.setGroupOperation(commission);
1492
 
 
1493
 
                                                        SKGSubOperationObject subcommission;
1494
 
                                                        if (err.isSucceeded()) err=commission.addSubOperation(subcommission);
1495
 
                                                        if (err.isSucceeded()) err=subcommission.setQuantity(-SKGServices::stringToDouble(val));
1496
 
                                                        if (err.isSucceeded()) err=subcommission.save(false, false);  //Save only whitout reload
1497
 
                                                } else if (op=='I') {
1498
 
                                                        //I     Price
1499
 
                                                        currentUnitPrice=SKGServices::stringToDouble(val);
1500
 
                                                        err=document->addOrModifyUnitValue(currentUnitForInvestment,
1501
 
                                                                                           currentOperationDate,
1502
 
                                                                                           currentUnitPrice);
1503
 
                                                } else if (op=='N') {
1504
 
                                                        if (investmentAccount) {
1505
 
                                                                //N     Action
1506
 
                                                                /*
1507
 
                                                                QIF N Line    Notes
1508
 
                                                                ============  =====
1509
 
                                                                Aktab         Same as ShrsOut.
1510
 
                                                                AktSplit      Same as StkSplit.
1511
 
                                                                Aktzu         Same as ShrsIn.
1512
 
                                                                Buy           Buy shares.
1513
 
                                                                BuyX          Buy shares. Used with an L line.
1514
 
                                                                Cash          Miscellaneous cash transaction. Used with an L line.
1515
 
                                                                CGMid         Mid-term capital gains.
1516
 
                                                                CGMidX        Mid-term capital gains. For use with an L line.
1517
 
                                                                CGLong        Long-term capital gains.
1518
 
                                                                CGLongX       Long-term capital gains. For use with an L line.
1519
 
                                                                CGShort       Short-term capital gains.
1520
 
                                                                CGShortX      Short-term capital gains. For use with an L line.
1521
 
                                                                ContribX      Same as XIn. Used for tax-advantaged accounts.
1522
 
                                                                CvrShrt       Buy shares to cover a short sale.
1523
 
                                                                CvrShrtX      Buy shares to cover a short sale. Used with an L line.
1524
 
                                                                Div           Dividend received.
1525
 
                                                                DivX          Dividend received. For use with an L line.
1526
 
                                                                Errinerg      Same as Reminder.
1527
 
                                                                Exercise      Exercise an option.
1528
 
                                                                ExercisX      Exercise an option. For use with an L line.
1529
 
                                                                Expire        Mark an option as expired. (Uses D, N, Y & M lines)
1530
 
                                                                Grant         Receive a grant of stock options.
1531
 
                                                                Int           Same as IntInc.
1532
 
                                                                IntX          Same as IntIncX.
1533
 
                                                                IntInc        Interest received.
1534
 
                                                                IntIncX       Interest received. For use with an L line.
1535
 
                                                                K.gewsp       Same as CGShort. (German)
1536
 
                                                                K.gewspX      Same as CGShortX. (German)2307068
1537
 
                                                                Kapgew        Same as CGLong. Kapitalgewinnsteuer.(German)
1538
 
                                                                KapgewX       Same as CGLongX. Kapitalgewinnsteuer. (German)
1539
 
                                                                Kauf          Same as Buy. (German)
1540
 
                                                                KaufX         Same as BuyX. (German)
1541
 
                                                                MargInt       Margin interest paid.
1542
 
                                                                MargIntX      Margin interest paid. For use with an L line.
1543
 
                                                                MiscExp       Miscellaneous expense.
1544
 
                                                                MiscExpX      Miscellaneous expense. For use with an L line.
1545
 
                                                                MiscInc       Miscellaneous income.
1546
 
                                                                MiscIncX      Miscellaneous income. For use with an L line.
1547
 
                                                                ReinvDiv      Reinvested dividend.
1548
 
                                                                ReinvInt      Reinvested interest.
1549
 
                                                                ReinvLG       Reinvested long-term capital gains.
1550
 
                                                                Reinvkur      Same as ReinvLG.
1551
 
                                                                Reinvksp      Same as ReinvSh.
1552
 
                                                                ReinvMd       Reinvested mid-term capital gains.
1553
 
                                                                ReinvSG       Same as ReinvSh.
1554
 
                                                                ReinvSh       Reinvested short-term capital gains.
1555
 
                                                                Reinvzin      Same as ReinvDiv.
1556
 
                                                                Reminder      Reminder. (Uses D, N, C & M lines)
1557
 
                                                                RtrnCap       Return of capital.
1558
 
                                                                RtrnCapX      Return of capital. For use with an L line.
1559
 
                                                                Sell          Sell shares.
1560
 
                                                                SellX         Sell shares. For use with an L line.
1561
 
                                                                ShtSell       Short sale.
1562
 
                                                                ShrsIn        Deposit shares.
1563
 
                                                                ShrsOut       Withdraw shares.
1564
 
                                                                StkSplit      Share split.
1565
 
                                                                Verkauf       Same as Sell. (German)
1566
 
                                                                VerkaufX      Same as SellX. (German)
1567
 
                                                                Vest          Mark options as vested. (Uses N, Y, Q, C & M lines)
1568
 
                                                                WithDrwX      Same as XOut. Used for tax-advantaged accounts.
1569
 
                                                                XIn           Transfer cash from another account.
1570
 
                                                                XOut          Transfer cash to another account.
1571
 
                                                                */
1572
 
                                                                val=val.toLower();
1573
 
                                                                if (val.contains("sell") || val.contains("verkauf") || val.contains("miscexp")) quantityFactor=-1;
 
1497
                                                                        if (err.isSucceeded()) err=defAccount.addOperation(commission);
 
1498
                                                                }
 
1499
                                                                if (err.isSucceeded()) err=commission.setDate(currentOperationDate);
 
1500
                                                                if (err.isSucceeded()) err=commission.setAttribute("t_imported", "P");
 
1501
                                                                if (err.isSucceeded()) {
 
1502
                                                                        //Create unit if needed
 
1503
                                                                        SKGUnitObject unit;
 
1504
                                                                        err=getDefaultUnit(unit, &currentOperationDate);
 
1505
                                                                        if (err.isSucceeded())  err=commission.setUnit(unit);
 
1506
                                                                }
 
1507
                                                                if (err.isSucceeded()) err=commission.save();  //Save only
 
1508
                                                                if (err.isSucceeded()) err=currentOperation.setGroupOperation(commission);
 
1509
 
 
1510
                                                                SKGSubOperationObject subcommission;
 
1511
                                                                if (err.isSucceeded()) err=commission.addSubOperation(subcommission);
 
1512
                                                                if (err.isSucceeded()) err=subcommission.setQuantity(-SKGServices::stringToDouble(val));
 
1513
                                                                if (err.isSucceeded()) err=subcommission.save(false, false);  //Save only whitout reload
 
1514
                                                        } else if (op=='I') {
 
1515
                                                                //I     Price
 
1516
                                                                currentUnitPrice=SKGServices::stringToDouble(val);
 
1517
                                                                err=document->addOrModifyUnitValue(currentUnitForInvestment,
 
1518
                                                                                                   currentOperationDate,
 
1519
                                                                                                   currentUnitPrice);
 
1520
                                                        } else if (op=='N') {
 
1521
                                                                if (investmentAccount) {
 
1522
                                                                        //N     Action
 
1523
                                                                        /*
 
1524
                                                                        QIF N Line    Notes
 
1525
                                                                        ============  =====
 
1526
                                                                        Aktab         Same as ShrsOut.
 
1527
                                                                        AktSplit      Same as StkSplit.
 
1528
                                                                        Aktzu         Same as ShrsIn.
 
1529
                                                                        Buy           Buy shares.
 
1530
                                                                        BuyX          Buy shares. Used with an L line.
 
1531
                                                                        Cash          Miscellaneous cash transaction. Used with an L line.
 
1532
                                                                        CGMid         Mid-term capital gains.
 
1533
                                                                        CGMidX        Mid-term capital gains. For use with an L line.
 
1534
                                                                        CGLong        Long-term capital gains.
 
1535
                                                                        CGLongX       Long-term capital gains. For use with an L line.
 
1536
                                                                        CGShort       Short-term capital gains.
 
1537
                                                                        CGShortX      Short-term capital gains. For use with an L line.
 
1538
                                                                        ContribX      Same as XIn. Used for tax-advantaged accounts.
 
1539
                                                                        CvrShrt       Buy shares to cover a short sale.
 
1540
                                                                        CvrShrtX      Buy shares to cover a short sale. Used with an L line.
 
1541
                                                                        Div           Dividend received.
 
1542
                                                                        DivX          Dividend received. For use with an L line.
 
1543
                                                                        Errinerg      Same as Reminder.
 
1544
                                                                        Exercise      Exercise an option.
 
1545
                                                                        ExercisX      Exercise an option. For use with an L line.
 
1546
                                                                        Expire        Mark an option as expired. (Uses D, N, Y & M lines)
 
1547
                                                                        Grant         Receive a grant of stock options.
 
1548
                                                                        Int           Same as IntInc.
 
1549
                                                                        IntX          Same as IntIncX.
 
1550
                                                                        IntInc        Interest received.
 
1551
                                                                        IntIncX       Interest received. For use with an L line.
 
1552
                                                                        K.gewsp       Same as CGShort. (German)
 
1553
                                                                        K.gewspX      Same as CGShortX. (German)2307068
 
1554
                                                                        Kapgew        Same as CGLong. Kapitalgewinnsteuer.(German)
 
1555
                                                                        KapgewX       Same as CGLongX. Kapitalgewinnsteuer. (German)
 
1556
                                                                        Kauf          Same as Buy. (German)
 
1557
                                                                        KaufX         Same as BuyX. (German)
 
1558
                                                                        MargInt       Margin interest paid.
 
1559
                                                                        MargIntX      Margin interest paid. For use with an L line.
 
1560
                                                                        MiscExp       Miscellaneous expense.
 
1561
                                                                        MiscExpX      Miscellaneous expense. For use with an L line.
 
1562
                                                                        MiscInc       Miscellaneous income.
 
1563
                                                                        MiscIncX      Miscellaneous income. For use with an L line.
 
1564
                                                                        ReinvDiv      Reinvested dividend.
 
1565
                                                                        ReinvInt      Reinvested interest.
 
1566
                                                                        ReinvLG       Reinvested long-term capital gains.
 
1567
                                                                        Reinvkur      Same as ReinvLG.
 
1568
                                                                        Reinvksp      Same as ReinvSh.
 
1569
                                                                        ReinvMd       Reinvested mid-term capital gains.
 
1570
                                                                        ReinvSG       Same as ReinvSh.
 
1571
                                                                        ReinvSh       Reinvested short-term capital gains.
 
1572
                                                                        Reinvzin      Same as ReinvDiv.
 
1573
                                                                        Reminder      Reminder. (Uses D, N, C & M lines)
 
1574
                                                                        RtrnCap       Return of capital.
 
1575
                                                                        RtrnCapX      Return of capital. For use with an L line.
 
1576
                                                                        Sell          Sell shares.
 
1577
                                                                        SellX         Sell shares. For use with an L line.
 
1578
                                                                        ShtSell       Short sale.
 
1579
                                                                        ShrsIn        Deposit shares.
 
1580
                                                                        ShrsOut       Withdraw shares.
 
1581
                                                                        StkSplit      Share split.
 
1582
                                                                        Verkauf       Same as Sell. (German)
 
1583
                                                                        VerkaufX      Same as SellX. (German)
 
1584
                                                                        Vest          Mark options as vested. (Uses N, Y, Q, C & M lines)
 
1585
                                                                        WithDrwX      Same as XOut. Used for tax-advantaged accounts.
 
1586
                                                                        XIn           Transfer cash from another account.
 
1587
                                                                        XOut          Transfer cash to another account.
 
1588
                                                                        */
 
1589
                                                                        val=val.toLower();
 
1590
                                                                        if (val.contains("sell") || val.contains("verkauf") || val.contains("miscexp")) quantityFactor=-1;
 
1591
                                                                        err=currentOperation.setComment(val);
 
1592
                                                                        if (err.isSucceeded()) err=currentOperation.setMode(tr("Title"));
 
1593
                                                                } else {
 
1594
                                                                        //N     Num (check or reference number)
 
1595
                                                                        //Set number
 
1596
                                                                        bool ok;
 
1597
                                                                        int number=val.toInt(&ok);
 
1598
                                                                        if (ok && number!=0) {
 
1599
                                                                                err=currentOperation.setNumber(number);
 
1600
                                                                        } else {
 
1601
                                                                                err=currentOperation.setMode(val);
 
1602
                                                                        }
 
1603
                                                                }
 
1604
                                                        } else if (op=='Q') {
 
1605
                                                                //Q     Quantity (number of shares or split ratio)
 
1606
                                                                //Set value
 
1607
                                                                err=currentSubOperation.setQuantity(quantityFactor*SKGServices::stringToDouble(val));
 
1608
                                                        } else if (op=='T') {
 
1609
                                                                //T     Amount
 
1610
                                                                //Set value
 
1611
                                                                err=currentSubOperation.setQuantity(SKGServices::stringToDouble(val)/currentUnitPrice);
 
1612
                                                                if (err.isSucceeded() && investmentAccount) {
 
1613
                                                                        err=currentOperation.setProperty("SKG_OP_ORIGINAL_AMOUNT", val);
 
1614
                                                                }
 
1615
                                                        } else if (op=='$') {
 
1616
                                                                //Dollar amount of split
 
1617
                                                                //Set value
 
1618
                                                                if (!investmentAccount) {
 
1619
                                                                        err=currentSubOperation.setQuantity(SKGServices::stringToDouble(val));
 
1620
 
 
1621
                                                                        //save
 
1622
                                                                        if (err.isSucceeded()) err=currentSubOperation.save();
 
1623
 
 
1624
                                                                        //Create suboperation
 
1625
                                                                        if (err.isSucceeded()) err=currentOperation.addSubOperation(currentSubOperation);
 
1626
 
 
1627
                                                                        latestSubCatMustBeRemoved=true;
 
1628
                                                                }
 
1629
                                                        } else if (op=='P') {
 
1630
                                                                //P Payee
 
1631
                                                                //Set Payee
 
1632
                                                                //Clean QIF coming from bankperfect
 
1633
                                                                val.remove("[auto]");
 
1634
 
 
1635
                                                                err=currentOperation.setPayee(val);
 
1636
                                                        } else if (op=='M') {
 
1637
                                                                //M     Memo
 
1638
                                                                //Set Memo
1574
1639
                                                                err=currentOperation.setComment(val);
1575
 
                                                                if (err.isSucceeded()) err=currentOperation.setMode(tr("Title"));
1576
 
                                                        } else {
1577
 
                                                                //N     Num (check or reference number)
1578
 
                                                                //Set number
1579
 
                                                                bool ok;
1580
 
                                                                int number=val.toInt(&ok);
1581
 
                                                                if (ok && number!=0) {
1582
 
                                                                        err=currentOperation.setNumber(number);
 
1640
                                                        } else if (op=='S' || op=='L') {
 
1641
                                                                //S     Category in split (Category/Transfer/Class)//L  Category (Category/Subcategory/Transfer/Class)
 
1642
                                                                //TODO LCategory of transaction
 
1643
                                                                //L[Transfer account]
 
1644
                                                                //LCategory of transaction/Class of transaction
 
1645
                                                                //L[Transfer account]/Class of transaction//Set Category
 
1646
                                                                SKGCategoryObject Category;
 
1647
                                                                val.replace('/', OBJECTSEPARATOR);
 
1648
                                                                val.replace(':', OBJECTSEPARATOR);
 
1649
                                                                val.replace(',', OBJECTSEPARATOR);
 
1650
                                                                val.replace(';', OBJECTSEPARATOR);
 
1651
                                                                err=SKGCategoryObject::createPathCategory(document,val, Category);
 
1652
                                                                if (err.isSucceeded())  err=currentSubOperation.setCategory(Category);
 
1653
                                                        } else if (op=='C') {
 
1654
                                                                //C     Cleared status
 
1655
                                                                //Set status
 
1656
                                                                err=currentOperation.setStatus((val=="C" ? SKGOperationObject::POINTED : (val=="R" ? SKGOperationObject::CHECKED : SKGOperationObject::NONE )));
 
1657
                                                        } else if (op=='^') {
 
1658
                                                                //^     End of entry
 
1659
                                                                //save
 
1660
 
 
1661
                                                                QByteArray hash = QCryptographicHash::hash(stringForHash.toUtf8(), QCryptographicHash::Md5);
 
1662
                                                                SKGObjectBase opWithThisHash;
 
1663
                                                                if (SKGObjectBase::getObject(document, "operation", "t_imported='Y' AND t_import_id='"+QString(hash.toHex())+'\'', opWithThisHash).isSucceeded()) {
 
1664
                                                                        err=currentOperation.remove();
 
1665
                                                                        nbOperationsNotImported++;
1583
1666
                                                                } else {
1584
 
                                                                        err=currentOperation.setMode(val);
 
1667
                                                                        if (err.isSucceeded()) err=currentOperation.setAttribute("t_imported", "P");
 
1668
                                                                        if (err.isSucceeded()) err=currentOperation.setImportID(hash.toHex());
 
1669
                                                                        if (err.isSucceeded()) err=currentOperation.save();
 
1670
                                                                        if (!latestSubCatMustBeRemoved && err.isSucceeded()) err=currentSubOperation.save();
1585
1671
                                                                }
1586
 
                                                        }
1587
 
                                                } else if (op=='Q') {
1588
 
                                                        //Q     Quantity (number of shares or split ratio)
1589
 
                                                        //Set value
1590
 
                                                        err=currentSubOperation.setQuantity(quantityFactor*SKGServices::stringToDouble(val));
1591
 
                                                } else if (op=='T') {
1592
 
                                                        //T     Amount
1593
 
                                                        //Set value
1594
 
                                                        err=currentSubOperation.setQuantity(SKGServices::stringToDouble(val)/currentUnitPrice);
1595
 
                                                        if (err.isSucceeded() && investmentAccount) {
1596
 
                                                                err=currentOperation.setProperty("SKG_OP_ORIGINAL_AMOUNT", val);
1597
 
                                                        }
1598
 
                                                } else if (op=='$') {
1599
 
                                                        //Dollar amount of split
1600
 
                                                        //Set value
1601
 
                                                        if (!investmentAccount) {
1602
 
                                                                err=currentSubOperation.setQuantity(SKGServices::stringToDouble(val));
1603
 
 
1604
 
                                                                //save
1605
 
                                                                if (err.isSucceeded()) err=currentSubOperation.save();
1606
 
 
1607
 
                                                                //Create suboperation
1608
 
                                                                if (err.isSucceeded()) err=currentOperation.addSubOperation(currentSubOperation);
1609
 
 
1610
 
                                                                latestSubCatMustBeRemoved=true;
1611
 
                                                        }
1612
 
                                                } else if (op=='P') {
1613
 
                                                        //P Payee
1614
 
                                                        //Set Payee
1615
 
                                                        //Clean QIF coming from bankperfect
1616
 
                                                        val.remove("[auto]");
1617
 
 
1618
 
                                                        err=currentOperation.setPayee(val);
1619
 
                                                } else if (op=='M') {
1620
 
                                                        //M     Memo
1621
 
                                                        //Set Memo
1622
 
                                                        err=currentOperation.setComment(val);
1623
 
                                                } else if (op=='S' || op=='L') {
1624
 
                                                        //S     Category in split (Category/Transfer/Class)//L  Category (Category/Subcategory/Transfer/Class)
1625
 
                                                        //TODO LCategory of transaction
1626
 
                                                        //L[Transfer account]
1627
 
                                                        //LCategory of transaction/Class of transaction
1628
 
                                                        //L[Transfer account]/Class of transaction//Set Category
1629
 
                                                        SKGCategoryObject Category;
1630
 
                                                        val.replace('/', OBJECTSEPARATOR);
1631
 
                                                        val.replace(':', OBJECTSEPARATOR);
1632
 
                                                        val.replace(',', OBJECTSEPARATOR);
1633
 
                                                        val.replace(';', OBJECTSEPARATOR);
1634
 
                                                        err=SKGCategoryObject::createPathCategory(document,val, Category);
1635
 
                                                        if (err.isSucceeded())  err=currentSubOperation.setCategory(Category);
1636
 
                                                } else if (op=='C') {
1637
 
                                                        //C     Cleared status
1638
 
                                                        //Set status
1639
 
                                                        err=currentOperation.setStatus((val=="C" ? SKGOperationObject::POINTED : (val=="R" ? SKGOperationObject::CHECKED : SKGOperationObject::NONE )));
1640
 
                                                } else if (op=='^') {
1641
 
                                                        //^     End of entry
1642
 
                                                        //save
1643
 
 
1644
 
                                                        QByteArray hash = QCryptographicHash::hash(stringForHash.toUtf8(), QCryptographicHash::Md5);
1645
 
                                                        SKGObjectBase opWithThisHash;
1646
 
                                                        if (SKGObjectBase::getObject(document, "operation", "t_imported='Y' AND t_import_id='"+QString(hash.toHex())+'\'', opWithThisHash).isSucceeded()) {
1647
 
                                                                err=currentOperation.remove();
1648
 
                                                                nbOperationsNotImported++;
 
1672
                                                                latestSubCatMustBeRemoved=false;
 
1673
                                                                currentUnitForInvestment="";
 
1674
                                                                quantityFactor=1;
 
1675
                                                                currentUnitPrice=1;
 
1676
                                                                stringForHash="";
1649
1677
                                                        } else {
1650
 
                                                                if (err.isSucceeded()) err=currentOperation.setAttribute("t_imported", "P");
1651
 
                                                                if (err.isSucceeded()) err=currentOperation.setImportID(hash.toHex());
1652
 
                                                                if (err.isSucceeded()) err=currentOperation.save();
1653
 
                                                                if (!latestSubCatMustBeRemoved && err.isSucceeded()) err=currentSubOperation.save();
 
1678
                                                                // A    Address (up to five lines; the sixth line is an optional message)
 
1679
                                                                // E    Memo in split
1654
1680
                                                        }
1655
 
                                                        latestSubCatMustBeRemoved=false;
1656
 
                                                        currentUnitForInvestment="";
1657
 
                                                        quantityFactor=1;
1658
 
                                                        currentUnitPrice=1;
1659
 
                                                        stringForHash="";
1660
 
                                                } else {
1661
 
                                                        // A    Address (up to five lines; the sixth line is an optional message)
1662
 
                                                        // E    Memo in split
1663
1681
                                                }
1664
 
                                        }
1665
 
 
1666
 
                                        if (err.isSucceeded() && i%100==0) err = SKGServices::executeSqliteOrder(document, "ANALYZE");
1667
 
                                        if (err.isSucceeded()) err=document->stepForward(i+1);
1668
 
                                }
1669
 
 
1670
 
                                if (err.isSucceeded()) err = SKGServices::executeSqliteOrder(document, "UPDATE operation SET t_imported='Y' WHERE t_imported='P'");
1671
 
 
1672
 
                                if (account) {
1673
 
                                        delete account;
1674
 
                                        account=NULL;
1675
 
                                }
1676
 
                                if (err.isSucceeded()) err=document->endTransaction(true);
1677
 
                                else  document->endTransaction(false);
1678
 
 
1679
 
                                if (err.isSucceeded() && nbOperationsNotImported)
1680
 
                                        err=document->sendMessage(tr("%1 operation(s) not imported because already existing").arg(nbOperationsNotImported));
1681
 
 
1682
 
                                //Lines treated
1683
 
                                if (err.isSucceeded()) err=document->stepForward(3);
 
1682
 
 
1683
                                                if (err.isSucceeded() && i%100==0) err = SKGServices::executeSqliteOrder(document, "ANALYZE");
 
1684
                                                if (err.isSucceeded()) err=document->stepForward(i+1);
 
1685
                                        }
 
1686
 
 
1687
                                        if (err.isSucceeded()) err = SKGServices::executeSqliteOrder(document, "UPDATE operation SET t_imported='Y' WHERE t_imported='P'");
 
1688
 
 
1689
                                        if (account) {
 
1690
                                                delete account;
 
1691
                                                account=NULL;
 
1692
                                        }
 
1693
                                        if (err.isSucceeded()) err=document->endTransaction(true);
 
1694
                                        else  document->endTransaction(false);
 
1695
 
 
1696
                                        if (err.isSucceeded() && nbOperationsNotImported)
 
1697
                                                err=document->sendMessage(tr("%1 operation(s) not imported because already existing").arg(nbOperationsNotImported));
 
1698
 
 
1699
                                        //Lines treated
 
1700
                                        if (err.isSucceeded()) err=document->stepForward(3);
 
1701
                                }
1684
1702
                        }
1685
1703
                }
 
1704
                if (err.isSucceeded()) err=document->endTransaction(true);
 
1705
                else  document->endTransaction(false);
1686
1706
        }
1687
 
        if (err.isSucceeded()) err=document->endTransaction(true);
1688
 
        else  document->endTransaction(false);
1689
1707
 
1690
1708
        if (err.isFailed()) {
1691
1709
                err.addError(ERR_FAIL, tr("%1 failed").arg("SKGImportExportManager::importQIF"));
1699
1717
        SKGError err;
1700
1718
        SKGTRACEINRC(2, "SKGImportExportManager::cleanBankImport", err);
1701
1719
 
1702
 
 
1703
1720
        //Begin transaction
1704
 
        err=document->beginTransaction("#INTERNAL#", 3);
1705
 
        if (err.isSucceeded()) {
1706
 
                //Step 1 Clean operations without mode and with comment with double space
1707
 
                SKGObjectBase::SKGListSKGObjectBase operations;
1708
 
                if (err.isSucceeded()) err=SKGObjectBase::getObjects(document, "operation", "t_mode='' and t_comment like '%  %'", operations);
1709
 
 
1710
 
                int nb=operations.count();
1711
 
                for (int i=0; err.isSucceeded() && i<nb ;++i) {
1712
 
                        SKGOperationObject op=operations[i];
1713
 
 
1714
 
                        //Comment is like this: <TYPE>  <INFO>
1715
 
                        //Example: RETRAIT DAB             20/01/08 11H44 013330 LCL GAILLAC 000497
1716
 
                        QRegExp rx("(.+) {2,}(.+)");
1717
 
                        QString comment=op.getComment();
1718
 
                        if (rx.indexIn(comment)!=-1) {
1719
 
                                //Get parameters
1720
 
                                QString mode =rx.cap(1);
1721
 
                                QString info =rx.cap(2);
1722
 
 
1723
 
                                //Modify
1724
 
                                err=op.setComment(info.trimmed());
1725
 
                                if (err.isSucceeded())  err=op.setMode(mode.trimmed());
1726
 
                                if (err.isSucceeded())  err=op.save(true, false); //No reload
1727
 
                        }
1728
 
                }
1729
 
 
1730
 
                //Step 1 done
1731
 
                if (err.isSucceeded()) err=document->stepForward(1);
1732
 
 
1733
 
                //Step 2 Clean operations without mode and with comment
1734
 
                if (err.isSucceeded()) err=SKGObjectBase::getObjects(document, "operation", "t_mode='' and t_comment!=''", operations);
1735
 
 
1736
 
                nb=operations.count();
1737
 
                for (int i=0; err.isSucceeded() && i<nb ;++i) {
1738
 
                        SKGOperationObject op=operations[i];
1739
 
 
1740
 
                        //Comment is like this: <TYPE> <INFO>
1741
 
                        //Example: RETRAIT DAB 14-05-16607-482390
1742
 
                        QRegExp rx("(\\S+) +(.+)");
1743
 
                        QString comment=op.getComment();
1744
 
                        if (rx.indexIn(comment)!=-1) {
1745
 
                                //Get parameters
1746
 
                                QString mode =rx.cap(1);
1747
 
                                QString info =rx.cap(2);
1748
 
 
1749
 
                                //Modify
1750
 
                                err=op.setComment(info.trimmed());
1751
 
                                if (err.isSucceeded())  err=op.setMode(mode.trimmed());
1752
 
                                if (err.isSucceeded())  err=op.save(true, false); //No reload
1753
 
                        }
1754
 
                }
1755
 
 
1756
 
                //Step 2 done
1757
 
                if (err.isSucceeded()) err=document->stepForward(2);
1758
 
 
1759
 
                //Step 3 Clean cheque without number
1760
 
                if (err.isSucceeded()) err=SKGObjectBase::getObjects(document, "operation", "i_number=0 and lower(t_mode)='cheque'", operations);
1761
 
 
1762
 
                nb=operations.count();
1763
 
                for (int i=0; err.isSucceeded() && i<nb ;++i) {
1764
 
                        SKGOperationObject op=operations[i];
1765
 
 
1766
 
                        //Comment is like this: <TYPE>  <INFO>
1767
 
                        //Example: RETRAIT DAB             20/01/08 11H44 013330 LCL GAILLAC 000497
1768
 
                        QRegExp rx("(\\d+)");
1769
 
                        QString comment=op.getComment();
1770
 
                        if (rx.indexIn(comment)!=-1) {
1771
 
                                //Get parameters
1772
 
                                int number =SKGServices::stringToInt(rx.cap(1));
1773
 
 
1774
 
                                //Modify
1775
 
                                err=op.setNumber(number);
1776
 
                                if (err.isSucceeded())  err=op.save(true, false); //No reload
1777
 
                        }
1778
 
                }
1779
 
 
1780
 
                //Step 3 done
1781
 
                if (err.isSucceeded()) err=document->stepForward(3);
 
1721
        if (document) {
 
1722
                err=document->beginTransaction("#INTERNAL#", 3);
 
1723
                if (err.isSucceeded()) {
 
1724
                        //Step 1 Clean operations without mode and with comment with double space
 
1725
                        SKGObjectBase::SKGListSKGObjectBase operations;
 
1726
                        if (err.isSucceeded()) err=SKGObjectBase::getObjects(document, "operation", "t_mode='' and t_comment like '%  %'", operations);
 
1727
 
 
1728
                        int nb=operations.count();
 
1729
                        for (int i=0; err.isSucceeded() && i<nb ;++i) {
 
1730
                                SKGOperationObject op=operations[i];
 
1731
 
 
1732
                                //Comment is like this: <TYPE>  <INFO>
 
1733
                                //Example: RETRAIT DAB             20/01/08 11H44 013330 LCL GAILLAC 000497
 
1734
                                QRegExp rx("(.+) {2,}(.+)");
 
1735
                                QString comment=op.getComment();
 
1736
                                if (rx.indexIn(comment)!=-1) {
 
1737
                                        //Get parameters
 
1738
                                        QString mode =rx.cap(1);
 
1739
                                        QString info =rx.cap(2);
 
1740
 
 
1741
                                        //Modify
 
1742
                                        err=op.setComment(info.trimmed());
 
1743
                                        if (err.isSucceeded())  err=op.setMode(mode.trimmed());
 
1744
                                        if (err.isSucceeded())  err=op.save(true, false); //No reload
 
1745
                                }
 
1746
                        }
 
1747
 
 
1748
                        //Step 1 done
 
1749
                        if (err.isSucceeded()) err=document->stepForward(1);
 
1750
 
 
1751
                        //Step 2 Clean operations without mode and with comment
 
1752
                        if (err.isSucceeded()) err=SKGObjectBase::getObjects(document, "operation", "t_mode='' and t_comment!=''", operations);
 
1753
 
 
1754
                        nb=operations.count();
 
1755
                        for (int i=0; err.isSucceeded() && i<nb ;++i) {
 
1756
                                SKGOperationObject op=operations[i];
 
1757
 
 
1758
                                //Comment is like this: <TYPE> <INFO>
 
1759
                                //Example: RETRAIT DAB 14-05-16607-482390
 
1760
                                QRegExp rx("(\\S+) +(.+)");
 
1761
                                QString comment=op.getComment();
 
1762
                                if (rx.indexIn(comment)!=-1) {
 
1763
                                        //Get parameters
 
1764
                                        QString mode =rx.cap(1);
 
1765
                                        QString info =rx.cap(2);
 
1766
 
 
1767
                                        //Modify
 
1768
                                        err=op.setComment(info.trimmed());
 
1769
                                        if (err.isSucceeded())  err=op.setMode(mode.trimmed());
 
1770
                                        if (err.isSucceeded())  err=op.save(true, false); //No reload
 
1771
                                }
 
1772
                        }
 
1773
 
 
1774
                        //Step 2 done
 
1775
                        if (err.isSucceeded()) err=document->stepForward(2);
 
1776
 
 
1777
                        //Step 3 Clean cheque without number
 
1778
                        if (err.isSucceeded()) err=SKGObjectBase::getObjects(document, "operation", "i_number=0 and lower(t_mode)='cheque'", operations);
 
1779
 
 
1780
                        nb=operations.count();
 
1781
                        for (int i=0; err.isSucceeded() && i<nb ;++i) {
 
1782
                                SKGOperationObject op=operations[i];
 
1783
 
 
1784
                                //Comment is like this: <TYPE>  <INFO>
 
1785
                                //Example: RETRAIT DAB             20/01/08 11H44 013330 LCL GAILLAC 000497
 
1786
                                QRegExp rx("(\\d+)");
 
1787
                                QString comment=op.getComment();
 
1788
                                if (rx.indexIn(comment)!=-1) {
 
1789
                                        //Get parameters
 
1790
                                        int number =SKGServices::stringToInt(rx.cap(1));
 
1791
 
 
1792
                                        //Modify
 
1793
                                        err=op.setNumber(number);
 
1794
                                        if (err.isSucceeded())  err=op.save(true, false); //No reload
 
1795
                                }
 
1796
                        }
 
1797
 
 
1798
                        //Step 3 done
 
1799
                        if (err.isSucceeded()) err=document->stepForward(3);
 
1800
                }
 
1801
 
 
1802
                if (err.isSucceeded()) err=document->endTransaction(true);
 
1803
                else  document->endTransaction(false);
1782
1804
        }
1783
1805
 
1784
 
        if (err.isSucceeded()) err=document->endTransaction(true);
1785
 
        else  document->endTransaction(false);
1786
 
 
1787
1806
        if (err.isFailed()) {
1788
1807
                err.addError(ERR_FAIL, tr("%1 failed").arg("SKGImportExportManager::cleanBankImport"));
1789
1808
        }
1796
1815
        SKGError err;
1797
1816
        SKGTRACEINRC(2, "SKGImportExportManager::cleanBankPerfectImport", err);
1798
1817
 
1799
 
 
1800
1818
        //Begin transaction
1801
 
        err=document->beginTransaction("#INTERNAL#", 5);
1802
 
        if (err.isSucceeded()) {
1803
 
                //Step 1 Clean cheque
1804
 
                err=SKGServices::executeSqliteOrder(document, "UPDATE operation set t_mode='Cheque', t_comment='', i_number=substr(t_mode,4,1000)+0 where t_mode like 'Chq %'");
1805
 
                if (err.isSucceeded()) err=SKGServices::executeSqliteOrder(document, "UPDATE operation set t_mode='Cheque', t_comment='', i_number=substr(t_comment,3,1000)+0 where t_mode like 'Ch%' AND t_comment like 'n%'");
1806
 
 
1807
 
                //Step 1 done
1808
 
                if (err.isSucceeded()) err=document->stepForward(1);
1809
 
 
1810
 
                //TODO Step 2 [auto]
1811
 
 
1812
 
                //Step 2 done
1813
 
                if (err.isSucceeded()) err=document->stepForward(2);
1814
 
 
1815
 
                //Step 3 Splitted operations
1816
 
                SKGStringListList listTmp;
1817
 
                if (err.isSucceeded()) err=SKGServices::executeSelectSqliteOrder(document,
1818
 
                                                   "SELECT id, d_date, t_comment, t_payee FROM operation WHERE i_group_id=0 AND t_payee like '[1/%'",
1819
 
                                                   listTmp);
1820
 
                int nb=listTmp.count();
1821
 
                for (int i=1; err.isSucceeded() && i<nb ;++i) { //First line ignored because of it's header
1822
 
                        QString id=listTmp.at(i).at(0);
1823
 
                        QString date=listTmp.at(i).at(1);
1824
 
                        QString comment=listTmp.at(i).at(2);
1825
 
                        QString payee=listTmp.at(i).at(3);
1826
 
                        QRegExp rx("(\\S+) +(.+)");
1827
 
                        if (rx.indexIn(payee)!=-1) {
1828
 
                                payee=SKGServices::stringToSqlString(rx.cap(2));
 
1819
        if (document) {
 
1820
                err=document->beginTransaction("#INTERNAL#", 5);
 
1821
                if (err.isSucceeded()) {
 
1822
                        //Step 1 Clean cheque
 
1823
                        err=SKGServices::executeSqliteOrder(document, "UPDATE operation set t_mode='Cheque', t_comment='', i_number=substr(t_mode,4,1000)+0 where t_mode like 'Chq %'");
 
1824
                        if (err.isSucceeded()) err=SKGServices::executeSqliteOrder(document, "UPDATE operation set t_mode='Cheque', t_comment='', i_number=substr(t_comment,3,1000)+0 where t_mode like 'Ch%' AND t_comment like 'n%'");
 
1825
 
 
1826
                        //Step 1 done
 
1827
                        if (err.isSucceeded()) err=document->stepForward(1);
 
1828
 
 
1829
                        //TODO Step 2 [auto]
 
1830
 
 
1831
                        //Step 2 done
 
1832
                        if (err.isSucceeded()) err=document->stepForward(2);
 
1833
 
 
1834
                        //Step 3 Splitted operations
 
1835
                        SKGStringListList listTmp;
 
1836
                        if (err.isSucceeded()) err=SKGServices::executeSelectSqliteOrder(document,
 
1837
                                                           "SELECT id, d_date, t_comment, t_payee FROM operation WHERE i_group_id=0 AND t_payee like '[1/%'",
 
1838
                                                           listTmp);
 
1839
                        int nb=listTmp.count();
 
1840
                        for (int i=1; err.isSucceeded() && i<nb ;++i) { //First line ignored because of it's header
 
1841
                                QString id=listTmp.at(i).at(0);
 
1842
                                QString date=listTmp.at(i).at(1);
 
1843
                                QString comment=listTmp.at(i).at(2);
 
1844
                                QString payee=listTmp.at(i).at(3);
 
1845
                                QRegExp rx("(\\S+) +(.+)");
 
1846
                                if (rx.indexIn(payee)!=-1) {
 
1847
                                        payee=SKGServices::stringToSqlString(rx.cap(2));
 
1848
                                }
 
1849
 
 
1850
                                QString wcop="d_date='"+date+"' AND t_comment='"+SKGServices::stringToSqlString(comment)+'\'';
 
1851
                                err=SKGServices::executeSqliteOrder(document,
 
1852
                                                                    "UPDATE suboperation SET rd_operation_id="+id+" WHERE "
 
1853
                                                                    "rd_operation_id!="+id+" AND rd_operation_id in (SELECT id FROM operation WHERE "+wcop+')');
 
1854
 
 
1855
                                if (err.isSucceeded()) err=SKGServices::executeSqliteOrder(document,
 
1856
                                                                   "DELETE FROM operation WHERE id!="+id+" AND "+wcop);
 
1857
 
 
1858
                                if (err.isSucceeded()) err=SKGServices::executeSqliteOrder(document,
 
1859
                                                                   "UPDATE operation SET t_comment='', t_payee='"+SKGServices::stringToSqlString(payee)+"' WHERE id="+id);
1829
1860
                        }
1830
1861
 
1831
 
                        QString wcop="d_date='"+date+"' AND t_comment='"+SKGServices::stringToSqlString(comment)+'\'';
1832
 
                        err=SKGServices::executeSqliteOrder(document,
1833
 
                                                            "UPDATE suboperation SET rd_operation_id="+id+" WHERE "
1834
 
                                                            "rd_operation_id!="+id+" AND rd_operation_id in (SELECT id FROM operation WHERE "+wcop+')');
1835
 
 
1836
 
                        if (err.isSucceeded()) err=SKGServices::executeSqliteOrder(document,
1837
 
                                                           "DELETE FROM operation WHERE id!="+id+" AND "+wcop);
1838
 
 
1839
 
                        if (err.isSucceeded()) err=SKGServices::executeSqliteOrder(document,
1840
 
                                                           "UPDATE operation SET t_comment='', t_payee='"+SKGServices::stringToSqlString(payee)+"' WHERE id="+id);
1841
 
                }
1842
 
 
1843
 
                //Step 3 done
1844
 
                if (err.isSucceeded()) err=document->stepForward(3);
1845
 
 
1846
 
                //Step 4 Titre
1847
 
                SKGObjectBase::SKGListSKGObjectBase opTitreList;
1848
 
                if (err.isSucceeded()) err=SKGObjectBase::getObjects(document, "operation", "t_mode='Titre'", opTitreList);
1849
 
 
1850
 
                int nb2=opTitreList.count();
1851
 
                for (int i=0; err.isSucceeded() && i<nb2 ;++i) {
1852
 
                        SKGOperationObject op=opTitreList[i];
1853
 
 
1854
 
                        //Payee is like this: <NB> <NAME> achet� <VALUE>
1855
 
                        //Example: 57.496 FCP EADS EXPANSION achet� 13,421
1856
 
                        QRegExp rx("(\\S+) (.+) \\S+ (\\S+)");
1857
 
                        QString payee=op.getPayee();
1858
 
                        if (rx.indexIn(payee)!=-1) {
1859
 
                                //Get parameters
1860
 
                                double nb=SKGServices::stringToDouble(rx.cap(1));
1861
 
                                QString unitName =rx.cap(2);
1862
 
                                double value=SKGServices::stringToDouble(rx.cap(3));
1863
 
 
1864
 
                                SKGObjectBase::SKGListSKGObjectBase subOps;
1865
 
                                err=op.getSubOperations(subOps);
1866
 
                                if (err.isSucceeded() && subOps.count()==1 && nb!=0) {
1867
 
 
1868
 
                                        //Create or Update unit
1869
 
                                        SKGSubOperationObject subOp=subOps.at(0);
1870
 
                                        SKGUnitObject unit(document);
1871
 
                                        if (err.isSucceeded())  err=document->addOrModifyUnitValue(unitName, op.getDate(), value);
1872
 
                                        if (err.isSucceeded())  err=document->addOrModifyUnitValue(unitName, QDate::currentDate(), subOp.getQuantity()/nb);
1873
 
                                        if (err.isSucceeded()) {
1874
 
                                                err=unit.setName(unitName);
1875
 
                                                if (err.isSucceeded())  err=unit.load();
 
1862
                        //Step 3 done
 
1863
                        if (err.isSucceeded()) err=document->stepForward(3);
 
1864
 
 
1865
                        //Step 4 Titre
 
1866
                        SKGObjectBase::SKGListSKGObjectBase opTitreList;
 
1867
                        if (err.isSucceeded()) err=SKGObjectBase::getObjects(document, "operation", "t_mode='Titre'", opTitreList);
 
1868
 
 
1869
                        int nb2=opTitreList.count();
 
1870
                        for (int i=0; err.isSucceeded() && i<nb2 ;++i) {
 
1871
                                SKGOperationObject op=opTitreList[i];
 
1872
 
 
1873
                                //Payee is like this: <NB> <NAME> achet� <VALUE>
 
1874
                                //Example: 57.496 FCP EADS EXPANSION achet� 13,421
 
1875
                                QRegExp rx("(\\S+) (.+) \\S+ (\\S+)");
 
1876
                                QString payee=op.getPayee();
 
1877
                                if (rx.indexIn(payee)!=-1) {
 
1878
                                        //Get parameters
 
1879
                                        double nb=SKGServices::stringToDouble(rx.cap(1));
 
1880
                                        QString unitName =rx.cap(2);
 
1881
                                        double value=SKGServices::stringToDouble(rx.cap(3));
 
1882
 
 
1883
                                        SKGObjectBase::SKGListSKGObjectBase subOps;
 
1884
                                        err=op.getSubOperations(subOps);
 
1885
                                        if (err.isSucceeded() && subOps.count()==1 && nb!=0) {
 
1886
 
 
1887
                                                //Create or Update unit
 
1888
                                                SKGSubOperationObject subOp=subOps.at(0);
 
1889
                                                SKGUnitObject unit(document);
 
1890
                                                if (err.isSucceeded())  err=document->addOrModifyUnitValue(unitName, op.getDate(), value);
 
1891
                                                if (err.isSucceeded())  err=document->addOrModifyUnitValue(unitName, QDate::currentDate(), subOp.getQuantity()/nb);
 
1892
                                                if (err.isSucceeded()) {
 
1893
                                                        err=unit.setName(unitName);
 
1894
                                                        if (err.isSucceeded())  err=unit.load();
 
1895
                                                }
 
1896
                                                if (err.isSucceeded())  err=unit.setType(SKGUnitObject::SHARE);
 
1897
                                                if (err.isSucceeded())  err=unit.setInternetCode(op.getComment());
 
1898
                                                if (err.isSucceeded())  err=unit.save();
 
1899
                                                if (err.isSucceeded())  err=op.setUnit(unit);
 
1900
                                                if (err.isSucceeded())  err=op.setPayee("");
 
1901
                                                if (err.isSucceeded())  err=subOp.setQuantity(nb);
 
1902
                                                if (err.isSucceeded())  err=subOp.save(true, false); //No reload
 
1903
                                                if (err.isSucceeded())  err=op.save(true, false); //No reload
1876
1904
                                        }
1877
 
                                        if (err.isSucceeded())  err=unit.setType(SKGUnitObject::SHARE);
1878
 
                                        if (err.isSucceeded())  err=unit.setInternetCode(op.getComment());
1879
 
                                        if (err.isSucceeded())  err=unit.save();
1880
 
                                        if (err.isSucceeded())  err=op.setUnit(unit);
1881
 
                                        if (err.isSucceeded())  err=op.setPayee("");
1882
 
                                        if (err.isSucceeded())  err=subOp.setQuantity(nb);
1883
 
                                        if (err.isSucceeded())  err=subOp.save(true, false); //No reload
1884
 
                                        if (err.isSucceeded())  err=op.save(true, false); //No reload
1885
1905
                                }
1886
1906
                        }
 
1907
 
 
1908
                        //Step 4 done
 
1909
                        if (err.isSucceeded()) err=document->stepForward(4);
 
1910
 
 
1911
                        //Step 5 Update payee with "Transfer" already defined as transfer
 
1912
                        if (err.isSucceeded()) err=SKGServices::executeSqliteOrder(document,
 
1913
                                                           "UPDATE operation SET t_payee='' WHERE t_payee like 'Transfert %' AND i_group_id!=0");
 
1914
 
 
1915
                        //Step 5 done
 
1916
                        if (err.isSucceeded()) err=document->stepForward(5);
1887
1917
                }
1888
 
 
1889
 
                //Step 4 done
1890
 
                if (err.isSucceeded()) err=document->stepForward(4);
1891
 
 
1892
 
                //Step 5 Update payee with "Transfer" already defined as transfer
1893
 
                if (err.isSucceeded()) err=SKGServices::executeSqliteOrder(document,
1894
 
                                                   "UPDATE operation SET t_payee='' WHERE t_payee like 'Transfert %' AND i_group_id!=0");
1895
 
 
1896
 
                //Step 5 done
1897
 
                if (err.isSucceeded()) err=document->stepForward(5);
 
1918
                if (err.isSucceeded()) err=document->endTransaction(true);
 
1919
                else  document->endTransaction(false);
1898
1920
        }
1899
 
        if (err.isSucceeded()) err=document->endTransaction(true);
1900
 
        else  document->endTransaction(false);
1901
 
 
1902
1921
        if (err.isFailed()) {
1903
1922
                err.addError(ERR_FAIL, tr("%1 failed").arg("SKGImportExportManager::cleanBankPerfectImport"));
1904
1923
        }
1914
1933
        oNbOperationsMerged=0;
1915
1934
 
1916
1935
        //Begin transaction
1917
 
        err=document->beginTransaction("#INTERNAL#", 2);
1918
 
        if (err.isSucceeded()) {
1919
 
                //Look for operations with
1920
 
                //  Same units
1921
 
                //  Same dates
1922
 
                //  Null i_group_id
1923
 
                //  Different accounts
1924
 
                //  Oposite amounts
1925
 
                SKGStringListList listTmp;
1926
 
                //TODO opimization
1927
 
                err=SKGServices::executeSelectSqliteOrder(document,
1928
 
                                "SELECT A.id, B.id FROM v_operation_tmp1 A, v_operation_tmp1 B WHERE A.id<=B.id AND A.rc_unit_id=B.rc_unit_id AND A.d_date=B.d_date AND A.rd_account_id!=B.rd_account_id AND A.f_QUANTITY=-B.f_QUANTITY AND A.i_group_id=0 AND B.i_group_id=0 AND A.f_QUANTITY!=0",
1929
 
                                listTmp);
1930
 
                //Step 1 done
1931
 
                if (err.isSucceeded()) err=document->stepForward(1);
1932
 
 
1933
 
                //Group
1934
 
                {
1935
 
                        oNbOperationsMerged=listTmp.count();
1936
 
                        if (err.isSucceeded()) err=document->beginTransaction("#INTERNAL#", oNbOperationsMerged-1);
1937
 
                        for (int i=1; err.isSucceeded() && i<oNbOperationsMerged ;++i) { //First line ignored because of it's header
1938
 
                                SKGOperationObject op1(document, SKGServices::stringToInt(listTmp.at(i).at(0)));
1939
 
                                SKGOperationObject op2(document, SKGServices::stringToInt(listTmp.at(i).at(1)));
1940
 
 
1941
 
                                err=op2.setGroupOperation(op1);
1942
 
                                if (err.isSucceeded()) err=op2.save(true, false); //No reload
1943
 
                                if (err.isSucceeded()) err=document->stepForward(i);
 
1936
        if (document) {
 
1937
                err=document->beginTransaction("#INTERNAL#", 2);
 
1938
                if (err.isSucceeded()) {
 
1939
                        //Look for operations with
 
1940
                        //  Same units
 
1941
                        //  Same dates
 
1942
                        //  Null i_group_id
 
1943
                        //  Different accounts
 
1944
                        //  Oposite amounts
 
1945
                        SKGStringListList listTmp;
 
1946
                        //+A.i_group_id=0 AND +B.i_group_id=0 is for avoiding to use bad index
 
1947
                        err=SKGServices::executeSelectSqliteOrder(document,
 
1948
                                        "SELECT A.id, B.id FROM v_operation_tmp1 A, v_operation_tmp1 B WHERE A.id<=B.id AND A.rc_unit_id=B.rc_unit_id AND A.d_date=B.d_date AND A.rd_account_id!=B.rd_account_id AND A.f_QUANTITY=-B.f_QUANTITY AND +A.i_group_id=0 AND +B.i_group_id=0 AND A.f_QUANTITY!=0",
 
1949
                                        listTmp);
 
1950
                        //Step 1 done
 
1951
                        if (err.isSucceeded()) err=document->stepForward(1);
 
1952
 
 
1953
                        //Group
 
1954
                        {
 
1955
                                oNbOperationsMerged=listTmp.count();
 
1956
                                if (err.isSucceeded()) err=document->beginTransaction("#INTERNAL#", oNbOperationsMerged-1);
 
1957
                                for (int i=1; err.isSucceeded() && i<oNbOperationsMerged ;++i) { //First line ignored because of it's header
 
1958
                                        SKGOperationObject op1(document, SKGServices::stringToInt(listTmp.at(i).at(0)));
 
1959
                                        SKGOperationObject op2(document, SKGServices::stringToInt(listTmp.at(i).at(1)));
 
1960
 
 
1961
                                        err=op2.setGroupOperation(op1);
 
1962
                                        if (err.isSucceeded()) err=op2.save(true, false); //No reload
 
1963
                                        if (err.isSucceeded()) err=document->stepForward(i);
 
1964
                                }
 
1965
                                if (err.isSucceeded()) err=document->endTransaction(true);
 
1966
                                else  document->endTransaction(false);
1944
1967
                        }
1945
 
                        if (err.isSucceeded()) err=document->endTransaction(true);
1946
 
                        else  document->endTransaction(false);
 
1968
                        oNbOperationsMerged=(oNbOperationsMerged-1)*2;
 
1969
 
 
1970
                        //Step 2 done
 
1971
                        if (err.isSucceeded()) err=document->stepForward(2);
 
1972
 
1947
1973
                }
1948
 
                oNbOperationsMerged=(oNbOperationsMerged-1)*2;
1949
 
 
1950
 
                //Step 2 done
1951
 
                if (err.isSucceeded()) err=document->stepForward(2);
1952
 
 
 
1974
                if (err.isSucceeded()) err=document->endTransaction(true);
 
1975
                else  document->endTransaction(false);
1953
1976
        }
1954
 
        if (err.isSucceeded()) err=document->endTransaction(true);
1955
 
        else  document->endTransaction(false);
1956
1977
 
1957
1978
        if (err.isFailed()) {
1958
1979
                err.addError(ERR_FAIL, tr("%1 failed").arg("SKGImportExportManager::findAndGroupTransfers"));