Accounting Software
Small Business Software Estimating Software
Unit Cost SoftwareConstruction Estimating SoftwareProject Estimating SoftwareCost Estimation SoftwareCost Estimating SoftwareConstruction Management SoftwareBusiness Management Software

Summation Calculators (Source Code)

Link to: header | unit cost directory

Copyright Turtle Creek Software 1996-2006. All Rights Reserved.

Comments

CCalcSummation

This class manages summation calculators in the Goldenseal accounting software,
estimating software, project management software and construction accounting software.

a list of calculations that are sums of other calculators

SUPERCLASS = DB_ArrayOwner

Constructor

/*********************************************************************************
default constructor
*********************************************************************************/
CCalcSummation::CCalcSummation()
{
mCurrentValue = 0;

mCalcDirty = true;
mDisplayDirty = false;
filler = 0;
mPadding = 0;

mEndSafetyTag = tag_endsafetytag; // TCS 9/7/02
}

Source Code

/*********************************************************************************

CopyFrom

copy the data members from the passed object. This is used to implement
duplicate. source should be an object of the same class as this object

*********************************************************************************/
void CCalcSummation::CopyFrom(DB_PersistentObject *source, const UInt8 copyFlags)
{
THE_SUPERCLASS::CopyFrom(source, copyFlags);

CCalcSummation *src = TCS_SAFE_CAST(source, CCalcSummation);
TCS_FailNILMsg(src, TCS_GetErrString(errID_BadRecord));

TCS_BlockMove(&src->mCurrentValue, &mCurrentValue, cCopyFileLength);
}/*********************************************************************************

GetFileLength

return the file length used by this object

*********************************************************************************/
NeoSize CCalcSummation::GetFileLength(const CNeoFormat *aFormat) const
{
return THE_SUPERCLASS::GetFileLength(aFormat) + cFileLength;
}/*********************************************************************************

GetMemberValue

return the value of the member with the given tag

*********************************************************************************/
Boolean CCalcSummation::GetMemberValue(const NeoTag aTag, const NeoTag aType,
void *aValue) const
{
switch (aTag)
{
case tag_currentvalue:
return ConvertMember(&mCurrentValue, type_money, aValue, aType);
break;

case tag_layouttag: // TCS 4/30/01
{
CTextString outString = CCalculatorList::GetCalculatorTagString(id_CalcSummation, GetDBID());
return ConvertMember(&outString, type_cstring, aValue, aType);
}
break;

default:
return THE_SUPERCLASS::GetMemberValue(aTag, aType, aValue);
break;
}
}/*********************************************************************************

SetMemberValue

set the value of the member with the given tag

*********************************************************************************/
Boolean CCalcSummation::SetMemberValue(const NeoTag aTag, const NeoTag aType,
const void *aValue)
{
switch (aTag)
{
case tag_currentvalue:
return ConvertMember(aValue, aType, &mCurrentValue, type_money);
break;

case tag_layouttag: // calculated, no need to set TCS 4/30/01
return true;
break;

default:
return THE_SUPERCLASS::SetMemberValue(aTag, aType, aValue);
break;
}
}/*********************************************************************************

ReadObject

read the persistent object's data in from a stream
*********************************************************************************/
void CCalcSummation::ReadObject(CNeoStream *aStream, const NeoTag aTag)
{
TCS_FailNILMsg(aStream, TCS_GetErrString(errID_BadStream));

CNeoDebugImport checker(aStream, this, cCheckTooSmall); // TCS 2/24/00

THE_SUPERCLASS::ReadObject(aStream, aTag);

if (!IsIOValid()) // TCS 2/5/02
return;

ReadSummationArrayFromStream(aStream, mEntries, cHasSafetyTag); // TCS 5/31/03

mCurrentValue.ReadFromStream(aStream); // mfs_sa 20feb2k3
*((UInt8*)&mCurrentValue + sizeof(mCurrentValue)) = aStream->ReadBits(2); // --Bitfield

mPadding = aStream->ReadChar();
mEndSafetyTag = aStream->ReadEndSafetyTag(this);

if (!IsValidEndTag(mEndSafetyTag))
ReportDamagedObject(GetDBClassID(), GetDBID());
}/*********************************************************************************

WriteObject

write the persistent object's data to a stream
*********************************************************************************/
void CCalcSummation::WriteObject(CNeoStream *aStream, const NeoTag aTag)
{
TCS_FailNILMsg(aStream, TCS_GetErrString(errID_BadStream));

// make sure we have valid data to write TCS 9/8/02
if (!IsValidEndTag(mEndSafetyTag))
{
ReportDamagedObject(GetDBClassID(), GetDBID());
mEndSafetyTag = tag_endsafetytag; // TCS 11/26/02
}

CNeoDebugExport checker(aStream, this, cCheckTooSmall);

if (!IsValidEndTag(mEndSafetyTag))
ReportDamagedObject(GetDBClassID(), GetDBID());

THE_SUPERCLASS::WriteObject(aStream, aTag);

WriteSummationArrayToStream(aStream, mEntries, cHasSafetyTag);

mCurrentValue.WriteToStream(aStream); // mfs_sa 20feb2k3
aStream->WriteChar(*((UInt8*)&mCurrentValue + sizeof(mCurrentValue))); // --Bitfield

aStream->WriteChar(mPadding);
aStream->WriteEndSafetyTag(mEndSafetyTag, this);
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************

GetTableColInfo

return information about table columns
*********************************************************************************/
Boolean CCalcSummation::CCalcSummations_Desc::GetTableColInfo(const TagType tag,
const TableIndexT col,
STableColInfo *colInfo)
{
if (tag == tag_summationstable)
{ // it's the summations table
switch (col)
{
case col_type:
colInfo->colType = coltype_menucv;
colInfo->fieldType = fieldtype_cv;
colInfo->colData = MENU_CalcSources;
TCS_BufferFromText(colInfo->colName,
TCS_GetStockString(stockID_Class), cTableColNameLength);
return true;
break;

case col_item:
colInfo->colType = coltype_cv;
colInfo->fieldType = fieldtype_cv;
colInfo->colData = id_CalculatorList; // value filled in at runtime
TCS_BufferFromText(colInfo->colName,
TCS_GetStockString(stockID_Calculation), cTableColNameLength);
return true;
break;

case col_subtotal:
colInfo->colType = coltype_caption;
colInfo->fieldType = fieldtype_money;
colInfo->colData = 0;
TCS_BufferFromText(colInfo->colName,
TCS_GetStockString(stockID_Amount), cTableColNameLength);
return true;
break;

default:
return false;
break;
}
}
else
return false;
}/*********************************************************************************

GetEntryFromRow

fill in the given percent data structure with info from the table

*********************************************************************************/
Boolean CCalcSummation::GetEntryFromRow(const CTCS_Table &aTable,
const TableIndexT row,
SSummationInfo *outInfo)
{
outInfo->calcType = aTable.GetCellValue(row, col_type);
outInfo->calcItem = aTable.GetCellValue(row, col_item);
outInfo->subtotal = CMoney(aTable.GetCellText(row, col_subtotal));
outInfo->filler = 0;

// we store only if an item was entered
return (outInfo->calcItem);
}/*********************************************************************************

FillRowFromEntry

fill the given table row with information from our entry

*********************************************************************************/
Boolean CCalcSummation::FillRowFromEntry(CTCS_Table *aTable, const TableIndexT row,
const SSummationInfo &inInfo)
{
if (inInfo.calcType && inInfo.calcItem) // TCS 1/13/02
{
aTable->SetCVCellValue(row, col_type, inInfo.calcType);
aTable->SetCVCellValue(row, col_item, inInfo.calcItem);

// we need to calculate an item total TCS 9/16/99
CMoney subTotal = 0;
DB_PersistentObject *calc = gDBFile->GetOneObject(inInfo.calcType, inInfo.calcItem);
if (calc)
{
DB_ObjectWatcher watcher(calc);
calc->SetCalcDirty(); // TCS 8/29/02
subTotal = calc->GetCalculatorMoney();
}
aTable->SetCellText(row, col_subtotal, subTotal.GetCurrencyString());

return true;
}
else
return false;
}
/*********************************************************************************

ExportColumnCString

return the value of a column element from our struct TCS 5/12/98

*********************************************************************************/
CTextString CCalcSummation::ExportColumnCString(const TableIndexT col,
const SSummationInfo &outInfo)
{
switch (col)
{
case col_item:
{
CTextString menuText;
if (FetchCVMenuText(col, outInfo.calcItem, &menuText))
return menuText.AppendCVExportString(outInfo.calcItem);
else
return cEmptyString;
}
break;

case col_type:
{
CTextString menuText;
if (FetchCVMenuText(col, outInfo.calcType, &menuText))
return menuText.AppendCVExportString(outInfo.calcType);
else
return cEmptyString;
}
break;

case col_subtotal:
return outInfo.subtotal.GetCurrencyString();
break;

default:
return cEmptyString;
break;
}
}
/*********************************************************************************

ImportColumnCString

fill a column element in our struct TCS 6/10/98

*********************************************************************************/
Boolean CCalcSummation::ImportColumnCString(const TableIndexT col,
const CTextString &inString, SSummationInfo *inInfo)
{
switch (col)
{
case col_item:
inInfo->calcItem = inString.ParseID();
return true;
break;

case col_type:
inInfo->calcType = inString.ParseID();
return true;
break;

case col_subtotal:
inInfo->subtotal = ConvertImportMoney(inString);
return true;
break;

default:
return false;
break;
}
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************

GetStarterCString TCS 12/18/00

return a starter value

*********************************************************************************/
CTextString CCalcSummation::GetStarterCString(const FormatType format) const
{
CMoney zero = 0;
return zero.GetFormatString(format); // rev TCS 5/7/04
}
/*********************************************************************************

GetDisplayCString

return the calculated text

*********************************************************************************/
CTextString CCalcSummation::GetDisplayCString(const UInt32 /*format*/, const Boolean alwaysUpdate)
{
SInt32 runLimit = 0; // TCS 4/9/02
UpdateCalculatorValue(runLimit, CMoney::GetDefaultMoneyFormat(), alwaysUpdate);

return mCurrentValue.GetCurrencyString();
}
/*********************************************************************************

GetCalculatorMoney

return the calculated money value.

*********************************************************************************/
CMoney CCalcSummation::GetCalculatorMoney()
{
SInt32 runLimit = 0; // TCS 4/9/02
return GetSummation(runLimit);
}
/*********************************************************************************

GetCalculatorInteger

return the integer value of a calculator.

*********************************************************************************/
SInt32 CCalcSummation::GetCalculatorInteger()
{
SInt32 runLimit = 0; // TCS 4/9/02
mCurrentValue = GetSummation(runLimit);
return mCurrentValue.GetDollars();
}
/*********************************************************************************
UpdateCalculatorValue rev TCS 12/19/00

calculate a value for this calculator. Note that we don't have to
remove from the database, since the length of a money never changes.

*********************************************************************************/
void CCalcSummation::UpdateCalculatorValue(SInt32 &runLimit, const FormatType /*format*/,
const Boolean alwaysUpdate)
{
runLimit++;
if (runLimit > cRecursionLimit) // TCS 4/9/02
{
TCS_DebugAlert("Oops, calculation too deep in CCalcCustom::UpdateCalculatorValue!");
return;
}

if (mDisplayDirty || mCalcDirty || alwaysUpdate) // rev TCS 12/31/00
{
mCurrentValue = GetSummation(runLimit);
mCalcDirty = false;
mDisplayDirty = false;
}
}
/*********************************************************************************

GetSummation TCS 9/3/99

calculate the sum of listed items

*********************************************************************************/
CMoney CCalcSummation::GetSummation(SInt32 &runLimit) const
{
// sanity check
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
CMoney value(0,0);
CTextString outString;
SInt32 counter = 0;
DB_PersistentObject *calculator = nil;

if (mEntries.GetCount() > 0)
{
SSummationInfo info;
CTmplArrayIterator<SSummationInfo> iterator(mEntries);

while (iterator.Next(info))
{
calculator = gDBFile->GetOneObject(info.calcType, info.calcItem);
if (calculator)
{
DB_ObjectWatcher watcher(calculator);

calculator->UpdateCalculatorValue(runLimit, CMoney::GetDefaultMoneyFormat());
value += calculator->GetCalculatorMoney();
}
}
}

return value;
}
/*********************************************************************************

SetDisplayDirty TCS 12/19/00

respond to a change in report conditions, and return whether a recalc is needed.
We need to pass it along to any linked calculators

*********************************************************************************/
Boolean CCalcSummation::SetDisplayDirty(const UInt8 source)
{
Boolean needsUpdate = false;

DB_PersistentObject *calculator = nil;

if (mEntries.GetCount() > 0)
{
SSummationInfo info;
CTmplArrayIterator<SSummationInfo> iterator(mEntries);

while (iterator.Next(info))
{
calculator = gDBFile->GetOneObject(info.calcType, info.calcItem);
if (calculator)
{
DB_ObjectWatcher watcher(calculator);

if (needsUpdate)
calculator->SetDisplayDirty(source);
else
needsUpdate = calculator->SetDisplayDirty(source);
}
}
}

if (source == calc_startup) // bugfix TCS 1/3/00
mDisplayDirty = true;
else if (source == calc_completed)
mDisplayDirty = false;
else if (needsUpdate)
mDisplayDirty = true;

return needsUpdate;
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************

CalculateDeduction TCS 7/26/99

calculate a deduction for the given amount and employee

*********************************************************************************/
CMoney CCalcSummation::CalculateDeduction(const CMoney &/*inAmount*/, CEmployeeAccount */*employee*/)
{
// %%%INCOMPLETE %%%%%%%%%%%%

return 0;
}
/*********************************************************************************

DependsOnCalc TCS 9/7/99

return whether or not this calculator depends on the listed calculator

*********************************************************************************/
Boolean CCalcSummation::DependsOnCalc(const UInt8 inClassID, const DBid inItemID, Boolean deeply) const
{
if (inClassID == id_CalcSummation && inItemID == GetDBID())
{ // the item id is the same as our id, and naturally
// we depend on ourselves!
return true;
}
else
{ // we need to look at each item in our list
CTCS_ArrayIterator iterator(mEntries);
SSummationInfo info;
while (iterator.Next(&info))
{
if (info.calcType == inClassID && info.calcItem == inItemID) // bugfix TCS 9/10/99
{
return true; // the item is used directly
}
else if (deeply && (inClassID == id_CalcCustom || inClassID == id_CalcSummation))
{ // we're looking deeply, so pass it on to calculators
DB_PersistentObject *calculator =
gDBFile->GetOneObject(info.calcType, info.calcItem);

if (calculator)
{
DB_ObjectWatcher watcher(calculator);
if (calculator->DependsOnCalc(inClassID, inItemID, deeply))
return true;
}
}
}
}
// if we got this far, it means we don't depend on the item
return false;
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************

FillDataReport TCS 9/7/02

fill in a diagnostic table that shows data field values.

*********************************************************************************/
void CCalcSummation::FillDataReport(CTCS_Table *table, CNeoStream *stream) const
{
TCS_FailNILMsg(table, TCS_GetErrString(errID_BadTable));
TCS_FailNILMsg(stream, TCS_GetErrString(errID_BadStream));

THE_SUPERCLASS::FillDataReport(table, stream);

FillFieldArrayRow(table, stream, "mEntries", mEntries);

NeoVersion version = GetVersion();

FillFieldTagRow(table, stream, tag_currentvalue, cMoneySize, mCurrentValue.GetCurrencyString());

FillFieldBitRow(table, stream, "mCalcDirty", mCalcDirty, true);
FillFieldBitRow(table, stream, "mDisplayDirty", mDisplayDirty);
FillFieldStockRow(table, stream, stockID_Padding, -6, SInt32(filler));
FillFieldStockRow(table, stream, stockID_Padding, cCharSize, SInt32(mPadding));

FillEndSafetyTag(table, stream, mEndSafetyTag);
}