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