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

Category Systems (Source Code 3)

Link to: header | source 1 | source 2 | unit cost directory

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

This class manages category systems in the Goldenseal accounting software,
estimating software, unit cost software, job costing software and construction estimating software.

Source Code

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

FillJobCostCompareArray (static) TCS 8/1/01

fill in an array of job cost compare structs. We just list all possible
categories or locations.

Note that if we have problems allocating arrays, we just assert and exit.
The caller should properly dispose of any arrays that were allocated
successfully, as part of its exception handling. Generally that's done via
a TRY/CATCH block followed by CReportTable::ClearJobCostCompareArray.
*********************************************************************************/
void CCategorySystem::FillJobCostCompareArray(TJobCostCompareArray &array,
const DBid reportID)
{
// we should always start with an empty array // TCS rev 4/15/02
TCS_ASSERTMsg(array.GetCount() == 0,
"Oops, array already filled in CCategorySystem::FillJobCostCompareArray!");

SJobCostCompareInfo info;
InitializeJobCostCompareInfo(info);

DBClass classID = id_Category; //rev TCS 11/7/01

if (reportID == id_JobCostLocationReport || reportID == id_JobCostLocationClassReport)
{
classID = id_Location;
}

TObjectIDArray idArray = DB_ListManager::GetIDArray(classID, cSortArray);

TObjectIDArrayIterator iterator(idArray);
DBid id;

while (iterator.Next(id))
{
info.id = id;
info.itemArray = NEW TObjectInfoArray; // TCS 1/29/02
TCS_FailNILMsg(info.itemArray, TCS_GetErrString(errID_BadArray)); // TCS rev 4/15/02
array.Append(info);
}

// also add an 'unallocated' item at the end.
info.id = 0;
info.itemArray = NEW TObjectInfoArray; // TCS 1/29/02
TCS_FailNILMsg(info.itemArray, TCS_GetErrString(errID_BadArray)); // TCS rev 4/15/02
array.Append(info);
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************

FillCategoryRowArray TCS 8/5/01

fill in row descriptions for a job cost category report.
*********************************************************************************/
void CCategorySystem::FillCategoryRowArray(TReportRowArray *rowInfoArray, const DBid reportID,
const Boolean includeItems,
TJobCostCompareArray &compareArray) const
{
switch (reportID)
{
case id_JobCostSubcatReport: // category headings with subcatagories
FillSubcategoryRowArray(rowInfoArray, includeItems, compareArray);
break;

case id_JobCostCatClassReport: // cost class headings with categories
FillCategoryClassRowArray(rowInfoArray, includeItems, compareArray);
break;

case id_JobCostCatReport: // a simple list of all categories in the system
FillCategoryRowArray(rowInfoArray, includeItems, compareArray);
break;

default:
break;
}
}
/*********************************************************************************

FillCategoryRowArray TCS 8/6/01

fill in row descriptions for a simple category report.
*********************************************************************************/
void CCategorySystem::FillCategoryRowArray(TReportRowArray *rowInfoArray,
const Boolean /*includeItems*/,
TJobCostCompareArray &/*compareArray*/) const
{
TCatArrayIterator iterator(mCategories);
SCatInfo catInfo;

SReportRowInfo rowInfo;
rowInfo.classID = id_Category;
rowInfo.matchValue = 0;
rowInfo.rowType = rowtype_categorycosts;
rowInfo.conditions = 0;

// we just create one array entry for each category
while (iterator.Next(catInfo))
{
rowInfo.itemID = catInfo.catID;
rowInfoArray->Append(rowInfo);
}

// finish with a row for unallocated items
rowInfo.itemID = 0;
rowInfoArray->Append(rowInfo);
}
/*********************************************************************************

FillSubcategoryRowArray TCS 8/6/01

fill in row descriptions for a subcategory report. We list categories as
headings, and subcategories beneath
*********************************************************************************/
void CCategorySystem::FillSubcategoryRowArray(TReportRowArray *rowInfoArray,
const Boolean includeItems, TJobCostCompareArray &/*compareArray*/) const
{
TCatArrayIterator iterator(mCategories);
SCatInfo catInfo;

SReportRowInfo rowInfo;
rowInfo.classID = id_Category;
rowInfo.matchValue = 0;
rowInfo.conditions = 0;

while (iterator.Next(catInfo))
{
// start with a category heading line
rowInfo.rowType = rowtype_subtitle;
rowInfo.itemID = catInfo.catID;
rowInfoArray->Append(rowInfo);

// now list each of the subcategories
TSubCatArrayIterator subIterator(*catInfo.subcatArray);
SSubcatInfo subcatInfo;

while (subIterator.Next(subcatInfo))
{
rowInfo.rowType = rowtype_categorycosts;
rowInfo.itemID = subcatInfo.subcatID;
rowInfoArray->Append(rowInfo);

if (includeItems) // TCS 1/30/02
{
}
}

// now an unallocated row (for items with this category but blank subcat)
rowInfo.rowType = rowtype_unallocatedcat;
rowInfo.itemID = catInfo.catID;
rowInfoArray->Append(rowInfo);

// then a subtotal line and a blank line
rowInfo.rowType = rowtype_subtotal;
rowInfo.itemID = 0;
rowInfoArray->Append(rowInfo);
rowInfo.rowType = rowtype_blank;
rowInfoArray->Append(rowInfo);
}

// finish with category lines for unallocated categories
rowInfo.itemID = cUnallocatedItem;
rowInfo.rowType = rowtype_subtitle;
rowInfoArray->Append(rowInfo);
rowInfo.itemID = 0;
rowInfo.rowType = rowtype_categorycosts;
rowInfoArray->Append(rowInfo);
rowInfo.rowType = rowtype_subtotal;
rowInfoArray->Append(rowInfo);
}
/*********************************************************************************

FillCategoryClassRowArray TCS 8/6/01

fill in row descriptions for a cost class and category report.
*********************************************************************************/
void CCategorySystem::FillCategoryClassRowArray(TReportRowArray *rowInfoArray,
const Boolean /*includeItems*/, TJobCostCompareArray &/*compareArray*/) const
{
SReportRowInfo rowInfo;
rowInfo.matchValue = 0;
rowInfo.conditions = 0;

TObjectIDArray idArray = DB_ListManager::GetIDArray(id_CategoryClass);
DBid id = 0, catID;

// add a 'zero' row so we pick up items with no class
idArray.Append(id);

// prepare to loop through all category classes
TObjectIDArrayIterator iterator(idArray);

while (iterator.Next(id))
{
TObjectIDArray catArray = GetCategoriesInClass(id);

if (catArray.GetCount() > 0)
{
// the cost class name
rowInfo.rowType = rowtype_subtitle;
rowInfo.classID = id_CategoryClass;
rowInfo.itemID = id;
rowInfoArray->Append(rowInfo);

// then fill in categories that belong
TObjectIDArrayIterator catIterator(catArray);

while (catIterator.Next(catID))
{
rowInfo.rowType = rowtype_categorycosts;
rowInfo.classID = id_Category;
rowInfo.itemID = catID;
rowInfoArray->Append(rowInfo);
}

// then subtotal and a blank row
rowInfo.rowType = rowtype_subtotal;
rowInfo.itemID = 0;
rowInfoArray->Append(rowInfo);
rowInfo.rowType = rowtype_blank;
rowInfoArray->Append(rowInfo);
}
}
}
/*********************************************************************************

FillDefaultCategoryRowArray (static) TCS 8/5/01

fill in row descriptions for a category report when there is no cat system
*********************************************************************************/
void CCategorySystem::FillDefaultCategoryRowArray(TReportRowArray *rowInfoArray,
const Boolean /*includeItems*/, TJobCostCompareArray &/*compareArray*/)
{
TCS_FailNILMsg(rowInfoArray, TCS_GetErrString(errID_BadArray));

// fill in basic info for a row struct
SReportRowInfo rowInfo;
rowInfo.classID = id_Category;
rowInfo.matchValue = 0;
rowInfo.rowType = rowtype_categorycosts;
rowInfo.conditions = 0;

// fetch an array all categories
TObjectIDArray idArray = DB_ListManager::GetIDArray(id_Category, cSortArray);
TObjectIDArrayIterator iterator(idArray);
DBid id;

// add every category to the row array
while (iterator.Next(id))
{
rowInfo.itemID = id;
rowInfoArray->Append(rowInfo);
}

// add an unallocated row TCS 2/10/03
rowInfo.itemID = 0;
rowInfoArray->Append(rowInfo);
}
/*********************************************************************************

FillCatSubcatArray TCS 7/10/02

fill in a two-level array of categories and subcategories. This creates a
bunch of arrays on the heap-- the caller is responsible for disposing of
them.
*********************************************************************************/
void CCategorySystem::FillCatSubcatArray(const DBid /*reportID*/, TTwoLevelArray *twoLevelArray,
const Boolean /*hideSoftCosts*/, CMoney &/*softCostAmount*/,
CMoney &/*hardCostAmount*/) const
{
TCS_FailNILMsg(twoLevelArray, TCS_GetErrString(errID_BadArray));

STwoLevelInfo reportCatInfo;
reportCatInfo.classID = id_Category;
reportCatInfo.groupArray = nil;
reportCatInfo.hasItems = false;

SReportGroupInfo reportSubcatInfo;
reportSubcatInfo.classID = id_Category;
reportSubcatInfo.conditions = 0;
reportSubcatInfo.itemArray = nil;

SCatInfo catInfo;
SSubcatInfo subcatInfo;

TCatArrayIterator catIterator (mCategories);

while (catIterator.Next(catInfo))
{
TCS_FailNILMsg(catInfo.subcatArray, TCS_GetErrString(errID_BadArray));

reportCatInfo.itemID = catInfo.catID;
reportCatInfo.groupArray = NEW TReportGroupArray;
TCS_FailNILMsg(reportCatInfo.groupArray, TCS_GetErrString(errID_BadArray));
twoLevelArray->Append(reportCatInfo);

TSubCatArrayIterator subcatIterator (*catInfo.subcatArray);

while (subcatIterator.Next(subcatInfo))
{
reportSubcatInfo.itemID = subcatInfo.subcatID;

reportSubcatInfo.itemArray = NEW TObjectInfoArray;
TCS_FailNILMsg(reportSubcatInfo.itemArray, TCS_GetErrString(errID_BadArray));

reportCatInfo.groupArray->Append(reportSubcatInfo);
}

// also create an 'unallocated' subcat
reportSubcatInfo.itemID = cUnallocatedItem;

reportSubcatInfo.itemArray = NEW TObjectInfoArray;
TCS_FailNILMsg(reportSubcatInfo.itemArray, TCS_GetErrString(errID_BadArray));

reportCatInfo.groupArray->Append(reportSubcatInfo);
}

// also create an 'unallocated' main category
reportCatInfo.itemID = cUnallocatedItem;
reportCatInfo.groupArray = NEW TReportGroupArray;
twoLevelArray->Append(reportCatInfo);

// the unallocated category needs a subcat array TCS 7/11/02
reportSubcatInfo.itemID = cUnallocatedItem;

reportSubcatInfo.itemArray = NEW TObjectInfoArray;
TCS_FailNILMsg(reportSubcatInfo.itemArray, TCS_GetErrString(errID_BadArray));

reportCatInfo.groupArray->Append(reportSubcatInfo);
}
/*********************************************************************************

FillCatItemArray TCS 1/25/03

fill in an array of categories and items. This creates arrays on the heap--
the caller is responsible for disposing of them.
*********************************************************************************/
void CCategorySystem::FillCatItemArray(const DBid /*reportID*/, TReportGroupArray *catArray) const
{
TCS_FailNILMsg(catArray, TCS_GetErrString(errID_BadArray));

SReportGroupInfo reportCatInfo;
reportCatInfo.classID = id_Category;
reportCatInfo.conditions = 0;
reportCatInfo.itemArray = nil;

TCatArrayIterator catIterator (mCategories);
SCatInfo catInfo;

while (catIterator.Next(catInfo))
{
reportCatInfo.itemID = catInfo.catID;
reportCatInfo.itemArray = NEW TObjectInfoArray;
TCS_FailNILMsg(reportCatInfo.itemArray, TCS_GetErrString(errID_BadArray));
catArray->Append(reportCatInfo);
}

// also create an 'unallocated' main category
reportCatInfo.itemID = cUnallocatedItem;
reportCatInfo.itemArray = NEW TObjectInfoArray;
catArray->Append(reportCatInfo);
}
/*********************************************************************************

FillDefaultCatSubcatArray (static) TCS 7/10/02

fill in a two-level array of all categories for a category/subcat/item breakdown,
when there is no category system.

This may never actually be used, since we generally use a cat/item array
when there is no category system.
*********************************************************************************/
void CCategorySystem::FillDefaultCatSubcatArray(TTwoLevelArray *twoLevelArray)
{
TCS_FailNILMsg(twoLevelArray, TCS_GetErrString(errID_BadArray));

STwoLevelInfo reportCatInfo;
reportCatInfo.classID = id_Category;
reportCatInfo.groupArray = nil;

SReportGroupInfo reportSubcatInfo;
reportSubcatInfo.classID = id_Category;
reportSubcatInfo.conditions = 0;
reportSubcatInfo.itemArray = nil;

TObjectIDArray catArray = DB_ListManager::GetIDArray(id_Category);

TObjectIDArrayIterator iterator(catArray);
DBid id;

while (iterator.Next(id))
{
reportCatInfo.itemID = id;
reportCatInfo.groupArray = NEW TReportGroupArray;
TCS_FailNILMsg(reportCatInfo.groupArray, TCS_GetErrString(errID_BadArray));
twoLevelArray->Append(reportCatInfo);

// create an 'unallocated' subcat for each category
reportSubcatInfo.itemID = 0;

reportSubcatInfo.itemArray = NEW TObjectInfoArray;
TCS_FailNILMsg(reportSubcatInfo.itemArray, TCS_GetErrString(errID_BadArray));

reportCatInfo.groupArray->Append(reportSubcatInfo);
}

// also create an 'unallocated' category
reportCatInfo.itemID = 0;
reportCatInfo.groupArray = NEW TReportGroupArray;
twoLevelArray->Append(reportCatInfo);

// the unallocated category needs a subcat array TCS 7/11/02
reportSubcatInfo.itemID = cUnallocatedItem;

reportSubcatInfo.itemArray = NEW TObjectInfoArray;
TCS_FailNILMsg(reportSubcatInfo.itemArray, TCS_GetErrString(errID_BadArray));

reportCatInfo.groupArray->Append(reportSubcatInfo);
}
/*********************************************************************************

FillDefaultCatItemArray (static) TCS 1/25/03

fill in an array of all categories for a category/item breakdown, when there
is no category system
*********************************************************************************/
void CCategorySystem::FillDefaultCatItemArray(TReportGroupArray *catArray)
{
TCS_FailNILMsg(catArray, TCS_GetErrString(errID_BadArray));

SReportGroupInfo catInfo;
catInfo.classID = id_Category;
catInfo.itemArray = nil;

TObjectIDArray idArray = DB_ListManager::GetIDArray(id_Category);

TObjectIDArrayIterator iterator(idArray);
DBid id;

while (iterator.Next(id))
{
catInfo.itemID = id;
catInfo.itemArray = NEW TObjectInfoArray;
TCS_FailNILMsg(catInfo.itemArray, TCS_GetErrString(errID_BadArray));
catArray->Append(catInfo);
}

// also create an 'unallocated' category
catInfo.itemID = cUnallocatedItem;
catInfo.itemArray = NEW TObjectInfoArray;
TCS_FailNILMsg(catInfo.itemArray, TCS_GetErrString(errID_BadArray));

catArray->Append(catInfo);
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************

FillCategoryNameArray (static) TCS 4/28/03

fill in an array of category names and id's
*********************************************************************************/
void CCategorySystem::FillCategoryNameArray(TNameIDArray &array, const DBid catSystemID)
{
#if TCS_MULTIUSER
if (gIsClient && gApplication)
{
// if this is client, we fetch the array from the server TCS 4/28/03
CTCS_NetworkMessage ioMessage(msg_FetchCategoryArray);
ioMessage.SetRecordID(catSystemID);
ioMessage.SetNeedsReply();

if (gApplication->BroadcastNetworkMessage(&ioMessage, cGiveWarning))
{
if (ioMessage.HasData())
{
// set up a stream to read the array
CTCS_NetworkStream stream(&ioMessage);

if (stream.ReadFromMessage()) // TCS 8/11/03
{
ReadNameIDArrayFromStream(&stream, array, cHasSafetyTag); // TCS rev 8/8/03
}
}
}

return;
}
#endif

TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));

DBid tempID = catSystemID;
if (!tempID)
tempID = GetDefaultCatSystem();

CCategorySystem *catSystem = TCS_SAFE_CAST(gDBFile->GetOneObject(id_CategorySystem, tempID),
CCategorySystem);

if (catSystem)
{
DB_ObjectWatcher watcher(catSystem);

catSystem->FillCatNameArray(array); // rev TCS 3/25/01 rev 4/28/03
}

// free up memory TCS 11/25/03
gDBFile->ForcePurge();
}

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

FillCatNameArray TCS 4/28/03

fill in an array of category names and id's
*********************************************************************************/
void CCategorySystem::FillCatNameArray(TNameIDArray &array) const
{
TCatArrayIterator iterator(mCategories);
SCatInfo info;
SNameIDInfo outInfo;
CTextString catName;

while (iterator.Next(info))
{
outInfo.id = info.catID;
catName = gDBFile->GetObjectName(id_Category, info.catID);

TCS_BufferFromText(outInfo.itemName, catName);

array.Append(outInfo);
}

if (GetPrefsBoolean(id_InterfacePrefs, tag_sortcategorynames)) // TCS 7/19/03
{
array.SortWithComparator(NEW CListNameComparator);
}
}
/*********************************************************************************

FillCategoryReport TCS 8/1/03

fill in a report of categories and subcategories.
*********************************************************************************/
void CCategorySystem::FillCategoryReport(CTextOutputStream &stream)
{
TCatArrayIterator iter(mCategories);
SCatInfo catInfo;
SSubcatInfo subcatInfo;
CTextString catName;

while (iter.Next(catInfo))
{
catName = gDBFile->GetObjectName(id_Category, catInfo.catID);
stream.WriteString(catName);
catName = CTextString(catInfo.code);
stream.WriteString(catName);
stream.WriteEndOfLine();

if (catInfo.subcatArray && catInfo.subcatArray->GetCount() > 0)
{
TSubCatArrayIterator subcatIter (*catInfo.subcatArray);

while (subcatIter.Next(subcatInfo))
{
catName = gDBFile->GetObjectName(id_Category, subcatInfo.subcatID);
stream.WriteTabs(1);
stream.WriteString(catName);
stream.WriteEndOfLine();
}
}
}
}
/*********************************************************************************

FillDataReport TCS 9/7/02

fill in a diagnostic table that shows data field values.

*********************************************************************************/
void CCategorySystem::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);

SInt32 categoryCount = mCategories.GetCount();
FillFieldTableRow(table, stream, "Category Count", cLongSize, categoryCount);
SCatInfo catInfo;
CTextString catName;
NeoMark mark;

TCatArrayIterator iterator(mCategories);

while (iterator.Next(catInfo))
{
// fetch the category name. The retrieval may reset the file mark, so we restore it
mark = stream->getMark();
catName = gDBFile->GetObjectName(id_Category, catInfo.catID);
stream->setMark(mark);

// fill in details for the category
FillFieldTableRow(table, stream, catName, cCatStructLength, cTwoDashString);
FillFieldArrayRow(table, stream, TCS_GetStockString(stockID_Subcat), *catInfo.subcatArray);
}

if (mCompAsPercent)
FillFieldTagRow(table, stream, tag_defaultcomprate, cMoneySize, mDefaultCompRate.GetPercentString());
else
FillFieldTagRow(table, stream, tag_defaultcomprate, cMoneySize, mDefaultCompRate.GetCurrencyString());

if (mTaxAsPercent)
FillFieldTagRow(table, stream, tag_defaulttaxrate, cMoneySize, mDefaultTaxRate.GetPercentString());
else
FillFieldTagRow(table, stream, tag_defaulttaxrate, cMoneySize, mDefaultTaxRate.GetCurrencyString());

FillFieldBitRow(table, stream, tag_taxaspercent, mTaxAsPercent, true);
FillFieldBitRow(table, stream, tag_compaspercent, mCompAsPercent);
FillFieldBitRow(table, stream, tag_requiresubcats, mRequireSubcats);
FillFieldBitRow(table, stream, tag_includeinstarter, mIncludeInStarterFile); // TCS 12/5/02
FillFieldStockRow(table, stream, stockID_Padding, -4, SInt32(filler));
FillFieldStockRow(table, stream, stockID_Padding, cCharSize, SInt32(mPadding));

FillEndSafetyTag(table, stream, mEndSafetyTag);
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************

AdjustCategoryArrays TCS 12/14/98

update the inclusion of this system in all categories it includes
*********************************************************************************/
void CCategorySystem::AdjustCategoryArrays(const Boolean removeIt)
{
TCatArrayIterator iterator(mCategories);
SCatInfo catInfo;
while (iterator.Next(catInfo))
{
// first update the category itself
AdjustCategoryArray(catInfo.catID, removeIt);

// then update all subcategories
TSubCatArrayIterator subIterator(*catInfo.subcatArray);
SSubcatInfo subcatInfo;
while (subIterator.Next(subcatInfo))
{
AdjustCategoryArray(subcatInfo.subcatID, removeIt);
}
}
}
/*********************************************************************************

AdjustCategoryArray TCS 12/14/98

update the inclusion of this system in a specific category
*********************************************************************************/
void CCategorySystem::AdjustCategoryArray(const DBid catID, const Boolean removeIt)
{
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));

CCategory *cat = TCS_SAFE_CAST(gDBFile->GetOneObject(id_Category, catID), CCategory);

if (cat)
{
DB_ObjectWatcher watcher(cat);

if (removeIt)
cat->RemoveCatSystem(GetDBID());
else
cat->AddCatSystem(GetDBID());
}
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************

GetDeductionAmount TCS 2/26/99 rev 5/9/00 rev 6/21/00 rev 3/28/02

compute the deduction amount for a comp or tax rate
*********************************************************************************/
CMoney CCategorySystem::GetDeductionAmount(const CMoney &baseAmount, const CMoney &hours,
const DBid category, const DBid subcategory,
CMoney &rate, Boolean &isPercent,
const Boolean isComp)
{
SCatInfo catInfo;
SSubcatInfo subcatInfo;
CMoney deductionAmount = 0;
Boolean foundCategory = false; // TCS 7/14/02

if (GetCatInfoFromRef(category, &catInfo))
{
if (subcategory)
{ // fetch rate from subcategory
// let's iterate the subcat array
CTmplArrayIterator<SSubcatInfo> iterator(*catInfo.subcatArray);
while (iterator.Next(subcatInfo))
{
if (subcatInfo.subcatID == subcategory)
{
if (isComp)
{
if (mCompAsPercent)
{
isPercent = true;
rate = subcatInfo.compRate;
deductionAmount = baseAmount * rate.GetPercentDecimal();
}
else
{
isPercent = false;
rate = subcatInfo.compRate;
deductionAmount = rate * hours; // rev TCS 6/21/00
}
}
else
{
if (mTaxAsPercent)
{
isPercent = true;
rate = subcatInfo.taxRate;
deductionAmount = baseAmount * rate.GetPercentDecimal();
}
else
{
isPercent = false;
rate = subcatInfo.taxRate;
deductionAmount = rate * hours;
}
}

foundCategory = true; // TCS 7/14/02
}
}
}
// no subcategory match, so use category rate
if (!foundCategory)
{
if (isComp)
{
if (mCompAsPercent)
{
isPercent = true;
rate = catInfo.compRate;
deductionAmount = baseAmount * rate.GetPercentDecimal();
}
else
{
isPercent = false;
rate = catInfo.compRate;
deductionAmount = rate * hours; // bugfix TCS 4/3/00
}
}
else
{
if (mTaxAsPercent)
{
isPercent = true;
rate = catInfo.taxRate;
deductionAmount = baseAmount * rate.GetPercentDecimal();
}
else
{
isPercent = false;
rate = catInfo.taxRate;
deductionAmount = rate * hours; // bugfix TCS 4/3/00
}
}
}

foundCategory = true;
}

// if we got this far, no category so use default rate
if (!foundCategory)
{
if (isComp)
{
if (mCompAsPercent)
{
isPercent = true;
rate = mDefaultCompRate;
deductionAmount = baseAmount * rate.GetPercentDecimal();
}
else
{
isPercent = false;
rate = mDefaultCompRate;
deductionAmount = rate * hours; // bugfix TCS 4/3/00
}
}
else
{
if (mTaxAsPercent)
{
isPercent = true;
rate = mDefaultTaxRate;
deductionAmount = baseAmount * rate.GetPercentDecimal();
}
else
{
isPercent = false;
rate = mDefaultTaxRate;
deductionAmount = rate * hours; // bugfix TCS 4/3/00
}
}
}

// now let's round to the nearest penny TCS 5/9/00
deductionAmount.RoundPennies();
return deductionAmount;
}