Brief description of class still missing. More...
#include <RecordList.h>
Public Member Functions | |
void | clear () |
QStringList | contracts () const |
double | countValid () const |
void | match (RecordList &o) |
void | preprocess (const QString &contract) |
void | preprocess () |
void | print () const |
void | print (Group::Category c) const |
bool | read (QString fileName, bool warning, AtomicBoolean &terminate) |
RecordList () | |
void | removeNull () |
QString | report () const |
void | setMode (Mode m) |
bool | setSupplierEquivalences (const QString &fileName, bool warning) |
~RecordList () | |
Static Public Member Functions | |
static bool | write (const QString &fileName, const RecordList &r1, const RecordList &r2) |
Brief description of class still missing.
Full description of class still missing
void RecordList::clear | ( | ) |
References TRACE.
Referenced by FileReader::run(), and ~RecordList().
{ TRACE; qDeleteAll(_groups); qDeleteAll(*this); _groups.clear(); QList<AccountingRecord *>::clear(); }
QStringList RecordList::contracts | ( | ) | const |
References AccountingRecord::contract(), and QGpCoreTools::unique().
{ QStringList l; for(int i=0; i<count(); i++) { AccountingRecord * r=(*this)[i]; l.append(r->contract()); } qSort(l); unique(l); return l; }
double RecordList::countValid | ( | ) | const |
Return the ratio of valid records compared to the total.
References AccountingRecord::category(), and Group::Valid.
{ int nValid=0; for(QList<AccountingRecord *>::const_iterator it=begin(); it!=end(); it++) { AccountingRecord * r=*it; if(r->category()==Group::Valid) { nValid++; } } return nValid/(double)count(); }
void RecordList::match | ( | RecordList & | o | ) |
References Group::Ambiguous, AccountingRecord::amount(), AccountingRecord::category(), Group::Cents, Group::CentsAmbiguous, AccountingRecord::compareString(), Group::DistinctAmount, Group::lessThan(), AccountingRecord::lessThanAmount(), Group::None, Group::SameAmount, Group::SameAmountAmbiguous, AccountingRecord::supplier(), and Group::Valid.
{ setN2(); o.setN2(); qSort(begin(), end(), AccountingRecord::lessThanAmount); qSort(o.begin(), o.end(), AccountingRecord::lessThanAmount); // Check for Valid for(int i=0; i<count(); i++) { AccountingRecord * r1=(*this)[i]; QList<AccountingRecord *> candidates2; if(r1->category()==Group::None) { int jStart=o.indexAfter(0.9*r1->amount()); int jEnd=o.indexAfter(1.1*r1->amount()); for(int j=jStart;j<jEnd ; j++) { AccountingRecord * r2=o[j]; if(r2->category()==Group::None && AccountingRecord::compareString(r1->supplier(), r2->supplier()) && fabs(r1->amount()-r2->amount())<0.005) { candidates2.append(r2); } } // Check for similar right after r1 QList<AccountingRecord *> candidates1; for(int k=i; k<count(); k++) { AccountingRecord * r=(*this)[k]; if(r->category()==Group::None) { if(AccountingRecord::compareString(r1->supplier(), r->supplier()) && fabs(r1->amount()-r->amount())<0.005) { candidates1.append(r); } else { break; } } } if(!candidates1.isEmpty() && !candidates2.isEmpty()) { groupCandidates(Group::Valid, Group::Ambiguous, candidates1, candidates2); } } } // Check for same amounts for(int i=0; i<count(); i++) { AccountingRecord * r1=(*this)[i]; QList<AccountingRecord *> candidates2; if(r1->category()==Group::None) { int jStart=o.indexAfter(0.9*r1->amount()); int jEnd=o.indexAfter(1.1*r1->amount()); for(int j=jStart;j<jEnd ; j++) { AccountingRecord * r2=o[j]; if(r2->category()==Group::None && fabs(r1->amount()-r2->amount())<0.005) { candidates2.append(r2); } } QList<AccountingRecord *> candidates1; for(int k=i; k<count(); k++) { AccountingRecord * r=(*this)[k]; if(r->category()==Group::None) { if(fabs(r1->amount()-r->amount())<0.005) { candidates1.append(r); } else { break; } } } if(!candidates1.isEmpty() && !candidates2.isEmpty()) { groupCandidates(Group::SameAmount, Group::SameAmountAmbiguous, candidates1, candidates2); } } } // Check for similar amounts: < 1 euro for(int i=0; i<count(); i++) { AccountingRecord * r1=(*this)[i]; QList<AccountingRecord *> candidates2; if(r1->category()==Group::None) { int jStart=o.indexAfter(0.9*r1->amount()); int jEnd=o.indexAfter(1.1*r1->amount()); for(int j=jStart;j<jEnd ; j++) { AccountingRecord * r2=o[j]; if(r2->category()==Group::None && fabs(r1->amount()-r2->amount())<0.1) { candidates2.append(r2); } } // Check for similar right after r1 QList<AccountingRecord *> candidates1; for(int k=i; k<count(); k++) { AccountingRecord * r=(*this)[k]; if(r->category()==Group::None) { if(fabs(r1->amount()-r->amount())<0.1) { candidates1.append(r); } else { break; } } } if(!candidates1.isEmpty() && !candidates2.isEmpty()) { groupCandidates(Group::Cents, Group::CentsAmbiguous, candidates1, candidates2); } } } // Check for similar amounts: < 10 cents for(int i=0; i<count(); i++) { AccountingRecord * r1=(*this)[i]; QList<AccountingRecord *> candidates2; if(r1->category()==Group::None) { int jStart=o.indexAfter(0.9*r1->amount()); int jEnd=o.indexAfter(1.1*r1->amount()); for(int j=jStart;j<jEnd ; j++) { AccountingRecord * r2=o[j]; if(r2->category()==Group::None && fabs(r1->amount()-r2->amount())<0.1) { candidates2.append(r2); } } // Check for similar right after r1 QList<AccountingRecord *> candidates1; for(int k=i; k<count(); k++) { AccountingRecord * r=(*this)[k]; if(r->category()==Group::None) { if(fabs(r1->amount()-r->amount())<0.1) { candidates1.append(r); } else { break; } } } if(!candidates1.isEmpty() && !candidates2.isEmpty()) { groupCandidates(Group::Cents, Group::CentsAmbiguous, candidates1, candidates2); } } } // Check for same suppliers and distinct amount for(int i=0; i<count(); i++) { AccountingRecord * r1=(*this)[i]; QList<AccountingRecord *> candidates2; if(r1->category()==Group::None) { for(int j=0;j<o.count() ; j++) { AccountingRecord * r2=o[j]; if(r2->category()==Group::None && AccountingRecord::compareString(r1->supplier(), r2->supplier())) { candidates2.append(r2); } } // Check for similar after r1 |(not only right after like before) QList<AccountingRecord *> candidates1; for(int k=i; k<count(); k++) { AccountingRecord * r=(*this)[k]; if(r->category()==Group::None) { if(AccountingRecord::compareString(r1->supplier(), r->supplier())) { candidates1.append(r); } } } if(!candidates1.isEmpty() && !candidates2.isEmpty()) { groupCandidates(Group::DistinctAmount, Group::DistinctAmount, candidates1, candidates2); } } } // Create groups for remaining records for(int i=0; i<count(); i++) { AccountingRecord * r=(*this)[i]; if(r->category()==Group::None) { QList<AccountingRecord *> candidates1, candidates2; candidates1.append(r); groupCandidates(Group::None, Group::None, candidates1, candidates2); } } for(int i=0; i<o.count(); i++) { AccountingRecord * r=o[i]; if(r->category()==Group::None) { QList<AccountingRecord *> candidates1, candidates2; candidates2.append(r); groupCandidates(Group::None, Group::None, candidates1, candidates2); } } qSort(_groups.begin(), _groups.end(), Group::lessThan); }
void RecordList::preprocess | ( | const QString & | contract | ) |
References Geslab, removeNull(), Sifac, and Sorgho.
{ switch(_mode) { case Sifac: keepContractOnly(contract); sumSifac(); removeNull(); removeSupplier("divers paie a facon"); break; case Geslab: setContract(contract); sumGeslab(); removeNull(); break; case Sorgho: keepContractOnly(contract); sumSorgho(); removeNull(); break; } }
void RecordList::preprocess | ( | ) |
void RecordList::print | ( | ) | const |
{
for(QList<AccountingRecord *>::const_iterator it=begin(); it!=end(); it++) {
(*it)->print();
}
}
void RecordList::print | ( | Group::Category | c | ) | const |
References AccountingRecord::category(), AccountingRecord::print(), and AccountingRecord::printChildren().
{ for(QList<AccountingRecord *>::const_iterator it=begin(); it!=end(); it++) { AccountingRecord * r=*it; if(r->category()==c) { r->print(); r->printChildren(); } } }
bool RecordList::read | ( | QString | fileName, |
bool | warning, | ||
AtomicBoolean & | terminate | ||
) |
References fileName, Geslab, MSG_ID, QGpCoreTools::LineParser::setDelimiters(), QGpCoreTools::LineParser::setSkipEmpty(), Sifac, Sorgho, QGpCoreTools::tr(), TRACE, and QGpCoreTools::AtomicBoolean::value().
Referenced by FileReader::run().
{ static const QString title(tr("Read file to compare")); TRACE; if(fileName.isEmpty()) { if(warning) { Message::warning(MSG_ID, title, tr("Empty file name")); } return false; } _fileName=fileName; QFile f(_fileName); if(!f.open(QIODevice::ReadOnly)) { if(warning) { Message::warning(MSG_ID, title, tr("Cannot open file %1 for reading").arg(_fileName)); } return false; } QTextStream s(&f); s.setCodec("IBM850"); LineParser lp; lp.setDelimiters("\t"); lp.setSkipEmpty(false); int lineNumber=0; switch(_mode) { case Sifac: if(!readHeaderSifac(s, lp, lineNumber)) { Message::warning(MSG_ID, title, tr("Cannot find header line in file %1").arg(_fileName)); return false; } break; case Geslab: if(!readHeaderGeslab(s, lp, lineNumber)) { s.seek(0); } break; case Sorgho: break; } bool ok; switch(_mode) { case Sifac: ok=readSifac(s, lp, lineNumber, terminate); break; case Geslab: ok=readGeslab(s, lp, lineNumber, terminate); break; case Sorgho: ok=readSorgho(s, lp, lineNumber, terminate); break; } if(!ok || terminate.value()) { return false; } if(isEmpty()) { Message::warning(MSG_ID, title, tr("Cannot find header line in file %1").arg(_fileName)); return false; } return true; }
void RecordList::removeNull | ( | ) |
References AccountingRecord::amount(), and QGpCoreTools::endl().
Referenced by preprocess().
{ int n=count(); for(int i=0; i<count(); ) { AccountingRecord * r=(*this)[i]; if(fabs(r->amount())<0.005) { delete takeAt(i); } else { i++; } } if(n>count()) { App::stream() << QString("Removed %1 null records\n").arg(n-count()) << endl; } }
QString RecordList::report | ( | ) | const |
References Group::Ambiguous, AccountingRecord::category(), Group::Cents, Group::CentsAmbiguous, Group::DistinctAmount, Group::None, Group::SameAmount, Group::SameAmountAmbiguous, QGpCoreTools::tr(), and Group::Valid.
{ int nValid=0, nAmbiguous=0, nSameAmount=0, nSameAmountAmbiguous=0, nCents=0, nCentsAmbiguous=0, nDistinctAmount=0, nNone=0; for(QList<AccountingRecord *>::const_iterator it=begin(); it!=end(); it++) { AccountingRecord * r=*it; switch(r->category()) { case Group::Valid: nValid++; break; case Group::Ambiguous: nAmbiguous++; break; case Group::SameAmount: nSameAmount++; break; case Group::SameAmountAmbiguous: nSameAmountAmbiguous++; break; case Group::Cents: nCents++; break; case Group::CentsAmbiguous: nCentsAmbiguous++; break; case Group::DistinctAmount: nDistinctAmount++; break; case Group::None: nNone++; break; } } return tr("Out of %1 records\n" "%2 records are valid\n" "%3 records are ambiguous\n" "%4 records have the same amount\n" "%5 records have same the amount with ambiguity\n" "%6 records differ only by less than 10 cents\n" "%7 records differ only by less than 10 cents with ambiguity\n" "%8 records have distinct amount\n" "%9 records have no match\n\n") .arg(count()) .arg(nValid) .arg(nAmbiguous) .arg(nSameAmount) .arg(nSameAmountAmbiguous) .arg(nCents) .arg(nCentsAmbiguous) .arg(nDistinctAmount) .arg(nNone); }
void RecordList::setMode | ( | Mode | m | ) | [inline] |
Referenced by FileReader::run().
{_mode=m;}
bool RecordList::setSupplierEquivalences | ( | const QString & | fileName, |
bool | warning | ||
) |
References MSG_ID, QGpCoreTools::LineParser::setDelimiters(), QGpCoreTools::LineParser::setSkipEmpty(), QGpCoreTools::LineParser::setString(), QGpCoreTools::LineParser::toString(), QGpCoreTools::tr(), and TRACE.
Referenced by FileReader::run().
{ TRACE; if(fileName.isEmpty()) { if(warning) { Message::warning(MSG_ID, tr("Supplier equivalences"), tr("Empty file name")); } return false; } QFile f(fileName); if(!f.open(QIODevice::ReadOnly)) { if(warning) { Message::warning(MSG_ID, tr("Supplier equivalences"), tr("Cannot open file %1 for reading").arg(fileName)); } return false; } QTextStream s(&f); s.setCodec("IBM850"); LineParser lp; lp.setDelimiters("\t"); lp.setSkipEmpty(false); int lineNumber=0; bool ok=true; _supplierEquivalence.clear(); while(!s.atEnd()) { lineNumber++; lp.setString(s.readLine()); QString key=lp.toString(0, ok); QString value=lp.toString(1, ok); if(!ok) { return false; } _supplierEquivalence.insert(key, value); } return true; }
bool RecordList::write | ( | const QString & | fileName, |
const RecordList & | r1, | ||
const RecordList & | r2 | ||
) | [static] |
References AccountingRecord::header(), MSG_ID, AccountingRecord::skip(), and QGpCoreTools::tr().
{ QFile f(fileName); if(!f.open(QIODevice::WriteOnly)) { Message::warning(MSG_ID, tr("Saving results"), tr("Error writing to file %1").arg(fileName)); return false; } QTextStream s(&f); s.setCodec("Windows-1252"); // Or incorrectly Windows ANSI, this is the default in Excel under Windows s << "\t" << r1._fileName; AccountingRecord::skip(s, r1._mode); s << "\t" << r2._fileName; AccountingRecord::skip(s, r2._mode); s << "\t\t\n"; s << tr("Contract\t"); AccountingRecord::header(s, r1._mode); s << "\t"; AccountingRecord::header(s, r2._mode); s << tr("\tCategory\tGroup\n"); for(int i=0; i<r1._groups.count(); i++) { r1._groups.at(i)->write(s, r1._mode, r2._mode, i+1); } return true; }