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