Link to: header | source
1 | source 3 | 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
/*********************************************************************************
GetCatInfo
return the information for the given category from its index
*********************************************************************************/
Boolean CCategorySystem::GetCatInfo(SInt32 catIndex, SCatInfo *outInfo) const
{
return mCategories.FetchItemAt(catIndex, *outInfo);
}/*********************************************************************************
GetSubcatInfo
return the information for the given subcategory from the index of cat & subcat
*********************************************************************************/
Boolean CCategorySystem::GetSubcatInfo(DBid catIndex,
SInt32 subcatIndex,
SSubcatInfo *outInfo) const
{
// first get the category info
SCatInfo catInfo;
if (GetCatInfo(catIndex, &catInfo))
{ // got the cat info, now let's get the subcat array
TSubCatArray *subArray = catInfo.subcatArray;
TCS_FailNILMsg(subArray,TCS_GetErrString(errID_BadArray));
return subArray->FetchItemAt(subcatIndex, *outInfo);
}
else
return false;
}
/*********************************************************************************
GetSubcatCount
return the number of subcategories for the given cat
*********************************************************************************/
SInt32 CCategorySystem::GetSubcatCount(const SInt32 catIndex)
{
// first get the category info
SCatInfo catInfo;
if (GetCatInfo(catIndex, &catInfo))
{ // got the cat info, now let's get the subcat array's count
TSubCatArray *subArray = catInfo.subcatArray;
if (subArray)
return subArray->GetCount();
else
return 0;
}
else
return 0;
}
/*********************************************************************************
GetCatInfoFromRef
return the information for the category with the given ref number
*********************************************************************************/
Boolean CCategorySystem::GetCatInfoFromRef(DBid ref, SCatInfo *outInfo) const
{
// sanity check
TCS_FailNILMsg(outInfo, TCS_GetErrString(errID_BadCatSystem));
// do a linear search for the ref
TCatArrayIterator iterator(mCategories);
while (iterator.Next(*outInfo))
{
if (outInfo->catID == ref)
return true;
}
// if we got here, means we didn't find the ref
return false;
}
/*********************************************************************************
GetSubcatInfoFromRef
return the information for the subcat with the given cat and subcat ref numbers
*********************************************************************************/
Boolean CCategorySystem::GetSubcatInfoFromRef(DBid catRef, DBid subcatRef,
SSubcatInfo *info) const
{
// sanity check
TCS_FailNILMsg(info, TCS_GetErrString(errID_BadCatSystem));
// first get the category
SCatInfo catInfo;
if (!GetCatInfoFromRef(catRef, &catInfo))
return nil;
// got the cat info, let's iterate the subcat array
CTmplArrayIterator<SSubcatInfo> iterator(*catInfo.subcatArray);
while (iterator.Next(*info))
{
if (info->subcatID == subcatRef)
return true;
}
// if we got here, means we didn't find the ref
return false;
}
/*********************************************************************************
GetCategoryCode TCS 3/28/01
return the code text for the given category
*********************************************************************************/
CTextString CCategorySystem::GetCategoryCode(const DBid category) const
{
SCatInfo info;
CTextString outString;
if (!category)
return outString;
// do a linear search for the ref
TCatArrayIterator iterator(mCategories);
while (iterator.Next(info))
{
if (info.catID == category)
{
outString = CTextString(info.code);
break;
}
}
return outString;
}
/*********************************************************************************
GetCategoryClass TCS 3/28/01
return the category class for the given category
*********************************************************************************/
DBid CCategorySystem::GetCategoryClass(const DBid category) const
{
SCatInfo info;
if (!category)
return 0;
// do a linear search for the ref
TCatArrayIterator iterator(mCategories);
while (iterator.Next(info))
{
if (info.catID == category)
{
return info.costClass;
}
}
return 0;
}
/*********************************************************************************
GetSubcatArray
return the subcat array for the given category
*********************************************************************************/
TSubCatArray *CCategorySystem::GetSubcatArray(const SInt32 catIndex) const
{
SCatInfo catInfo;
if (GetCatInfo(catIndex, &catInfo))
return catInfo.subcatArray;
else
return nil;
}
/*********************************************************************************
GetSubcatArrayFromRef
return the subcat array for the given category by ref. This is used
for building menu arrays
*********************************************************************************/
TSubCatArray *CCategorySystem::GetSubcatArrayFromRef(DBid catRef) const
{
SCatInfo catInfo;
if (GetCatInfoFromRef(catRef, &catInfo))
return catInfo.subcatArray;
else
return nil;
}
/*********************************************************************************
GetCategoriesInClass TCS 8/6/01
get a list of categories that belong to the given category class
*********************************************************************************/
TObjectIDArray CCategorySystem::GetCategoriesInClass(const DBid catClassID) const
{
TObjectIDArray outArray;
TCatArrayIterator iterator(mCategories);
SCatInfo info;
while (iterator.Next(info))
{
if (info.costClass == catClassID)
outArray.Append(info.catID);
}
return outArray;
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
AddCategory
add a newly created category. TCS removed params since not actually used 12/14/98
*********************************************************************************/
void CCategorySystem::AddCategory()
{
SCatInfo catInfo;
InitializeCatInfo(catInfo);
mCategories.Append(catInfo);
}/*********************************************************************************
AddSubcatToCatByRef
add a subcategory to the cat with the given ref
*********************************************************************************/
DBid CCategorySystem::AddSubcatToCatByRef(DBid catID, DBid subcatID,
CMoney taxRate, CMoney compRate)
{
// first get the cat info
SCatInfo catInfo;
TCS_ASSERTMsg(GetCatInfoFromRef(catID, &catInfo), TCS_GetErrString(errID_BadCatSystem));
// got it, now append the subcat
return AddSubcatToCat(catInfo, subcatID, taxRate, compRate);
}/*********************************************************************************
AddSubcatToCatByIndex
add a subcategory to the cat with the given index
*********************************************************************************/
DBid CCategorySystem::AddSubcatToCatByIndex(const SInt32 catIndex, DBid subcatID,
CMoney taxRate, CMoney compRate)
{
// first get the cat info
SCatInfo catInfo;
TCS_ASSERTMsg(GetCatInfo(catIndex, &catInfo), TCS_GetErrString(errID_BadCatSystem));
// got it, now append the subcat
return AddSubcatToCat(catInfo, subcatID, taxRate, compRate);
}/*********************************************************************************
AddSubcatToCat
add a subcategory to the cat
*********************************************************************************/
DBid CCategorySystem::AddSubcatToCat(const SCatInfo &catInfo, DBid subcatID,
CMoney taxRate, CMoney compRate)
{
// sanity check
TCS_FailNILMsg(catInfo.subcatArray, TCS_GetErrString(errID_BadArray));
// fill in the subcat information and append it
// to the cat's subcat array
SSubcatInfo subInfo;
subInfo.subcatID = subcatID;
subInfo.taxRate = taxRate;
subInfo.compRate = compRate;
catInfo.subcatArray->Append(subInfo);
return subcatID;
}
#if CAN_USE_MARK
#pragma mark -
#endif/*********************************************************************************
DeleteNamelessCats
delete categories with empty names
*********************************************************************************/
void CCategorySystem::DeleteNamelessCats()
{
SCatInfo catInfo;
SSubcatInfo subcatInfo;
TCatArrayIterator iterator(mCategories);
while (iterator.Next(catInfo))
{
if (catInfo.catID == 0)
{ // the category is empty
mCategories.Remove(catInfo);
TCS_Forget(catInfo.subcatArray); // TCS rev 11/5/00
}
else // remove nameless subcats TCS 7/5/00
{
TSubCatArrayIterator iterator(*catInfo.subcatArray);
while (iterator.Next(subcatInfo))
{
if (subcatInfo.subcatID == 0)
{
catInfo.subcatArray->Remove(subcatInfo);
}
}
}
}
}/*********************************************************************************
DeleteAllCats
kill all the current categories
*********************************************************************************/
void CCategorySystem::DeleteAllCats()
{
// must kill the subcat arrays. We place this in its own
// block so that the iterator will be disposed of
// before RemoveAllItems is called on the main array
{
TCatArrayIterator iterator(mCategories);
SCatInfo catInfo;
while (iterator.Next(catInfo))
{
TCS_Forget(catInfo.subcatArray); // TCS rev 11/5/00
}
}
// remove all the items in the category array
mCategories.RemoveAllItems();
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
IncludesCategory TCS 12/14/98
return whether the given category id is included in this system
*********************************************************************************/
Boolean CCategorySystem::IncludesCategory(const DBid catID, const Boolean subcatsAlso)
{
TCatArrayIterator iterator(mCategories);
SCatInfo catInfo;
while (iterator.Next(catInfo))
{
// first check the category itself
if (catInfo.catID == catID)
return true;
if (subcatsAlso)
{
// then check all subcategories
TSubCatArrayIterator subIterator(*catInfo.subcatArray);
SSubcatInfo subcatInfo;
while (subIterator.Next(subcatInfo))
{
if (subcatInfo.subcatID == catID)
return true;
}
}
}
// if we got this far, it's not included
return false;
}
/*********************************************************************************
HasSubcategories TCS 7/30/01
return whether this cat system has any subcategories
*********************************************************************************/
Boolean CCategorySystem::HasSubcategories() const
{
TCatArrayIterator iterator(mCategories);
SCatInfo info;
// loop thru each category and see if it has subcategories
while (iterator.Next(info))
{
if (info.subcatArray->GetCount() > 0)
return true;
}
// if we get this far, there are no subcategories
return false;
}
/*********************************************************************************
HandleCategoryMove TCS 11/27/01 rev 8/13/02
deal with a category that has been re-ordered
*********************************************************************************/
void CCategorySystem::HandleCategoryMove(const SMoveInfo moveInfo)
{
SInt32 sourceRow = ROW(moveInfo.source),
targetRow = ROW(moveInfo.target);
if (sourceRow == targetRow)
return;
SCatInfo sourceCat,
targetCat;
if (sourceRow < targetRow)
{
// moving down
for (SInt32 row = sourceRow; row < targetRow; row++)
{
mCategories.FetchItemAt(row, sourceCat);
mCategories.FetchItemAt(row + 1, targetCat);
mCategories.AssignItemAt(row + 1, sourceCat);
mCategories.AssignItemAt(row, targetCat);
}
}
else
{
// moving up
for (SInt32 row = sourceRow; row > targetRow; row--)
{
mCategories.FetchItemAt(row, sourceCat);
mCategories.FetchItemAt(row - 1, targetCat);
mCategories.AssignItemAt(row - 1, sourceCat);
mCategories.AssignItemAt(row, targetCat);
}
}
}
/*********************************************************************************
HandleCategoryInsertion TCS 7/1/03
deal with a category that has been added in the middle of a table. We
just add a blank item. It will be filled in later when we read data from
the table.
*********************************************************************************/
void CCategorySystem::HandleCategoryInsertion(const TableIndexT row)
{
SCatInfo catInfo;
InitializeCatInfo(catInfo);
mCategories.InsertItemAt(row, catInfo);
}
/*********************************************************************************
HandleCategoryDeleted TCS 7/1/03
deal with a category that has been deleted in the middle of a table
*********************************************************************************/
void CCategorySystem::HandleCategoryDeleted(const TableIndexT row)
{
mCategories.RemoveItemAt(row);
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
InitializeCatInfo (static) split TCS 7/1/03
fill in default values for a SCatInfo struct, and allocate a subcategory
array. Caller is responsible for deleting the array.
*********************************************************************************/
void CCategorySystem::InitializeCatInfo(SCatInfo &catInfo)
{
catInfo.costClass = 0;
catInfo.catID = 0;
catInfo.code[0] = nil;
catInfo.filler = 0; // TCS 6/17/03
catInfo.taxRate = 0;
catInfo.compRate = 0;
catInfo.subcatArray = NEW TSubCatArray;
TCS_FailNILMsg(catInfo.subcatArray, TCS_GetErrString(errID_BadArray));
}
/*********************************************************************************
InitializeJobCostReportInfo (static) TCS 12/22/99
initialize a job cost report info struct
*********************************************************************************/
void CCategorySystem::InitializeJobCostReportInfo(SJobCostReportInfo &costInfo)
{
costInfo.id = 0;
costInfo.equipmentAmount = 0;
costInfo.laborAmount = 0;
costInfo.materialAmount = 0;
costInfo.subcontractorAmount = 0;
costInfo.otherAmount = 0;
costInfo.softAmount = 0; // TCS 8/1/01
costInfo.overheadAmount = 0;
costInfo.contractAmount = 0;
costInfo.incomeAmount = 0;
costInfo.percentCompleted = 0;
}
/*********************************************************************************
InitializeJobCostCategoryInfo TCS 7/30/01
initialize a job cost category info struct
*********************************************************************************/
void CCategorySystem::InitializeJobCostCategoryInfo(SJobCostCategoryInfo &costInfo)
{
costInfo.equipmentAmount = 0;
costInfo.laborAmount = 0;
costInfo.materialAmount = 0;
costInfo.subcontractorAmount = 0;
costInfo.otherAmount = 0;
costInfo.contractAmount = 0;
costInfo.incomeAmount = 0;
costInfo.changeAmount = 0;
}
/*********************************************************************************
InitializeJobCostCompareInfo TCS 8/1/01
initialize a job cost comparison info struct
*********************************************************************************/
void CCategorySystem::InitializeJobCostCompareInfo(SJobCostCompareInfo &costInfo)
{
costInfo.estEquipment = 0;
costInfo.estLabor = 0;
costInfo.estMaterials = 0;
costInfo.estSubcontractors = 0;
costInfo.estOther = 0;
costInfo.estSoft = 0;
costInfo.actualEquipment = 0;
costInfo.actualLabor = 0;
costInfo.actualMaterials = 0;
costInfo.actualSubcontractors = 0;
costInfo.actualOther = 0;
costInfo.actualSoft = 0;
costInfo.percentDone = 0;
costInfo.valueCompleted = 0;
// start with a nil array.
costInfo.itemArray = nil; // TCS 1/29/02
}
/*********************************************************************************
InitializeJobCostClassInfo TCS 8/1/01
initialize a job cost comparison info struct
*********************************************************************************/
/*void CCategorySystem::InitializeJobCostClassInfo(SJobCostClassInfo &costInfo)
{
InitializeJobCostCompareInfo(costInfo.totalInfo);
costInfo.subcatArray = nil;
}*/
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
FillCostReportArray
fill a cost array with categories. This struct is used for progress billing
*********************************************************************************/
Boolean CCategorySystem::FillCostReportArray(TJobCostReportArray &costArray) const
{
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
// initialize a struct
SJobCostReportInfo costInfo;
InitializeJobCostReportInfo(costInfo);
// prepare to iterate
SCatInfo catInfo;
CTextString catName;
TCatArrayIterator iterator(mCategories);
// loop thru categories and add them to the array
while (iterator.Next(catInfo))
{
costInfo.id = catInfo.catID;
// fetch the category name
if (!gDBFile->GetObjectName(id_Category, catInfo.catID, catName))
{
catName = TCS_GetStockString(stockID_MissingItem);
}
TCS_BufferFromText(costInfo.catName, catName);
costArray.Append(costInfo);
}
return true;
}
/*********************************************************************************
FillCostCategoryArray TCS 9/9/98
fill a cost array with categories. This struct is used for job costs.
*********************************************************************************/
Boolean CCategorySystem::FillCostCategoryArray(TJobCostCategoryArray &costArray) const
{
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
// initialize a cat info struct
SJobCostCategoryInfo costInfo;
InitializeJobCostCategoryInfo(costInfo);
// prepare to iterate
SCatInfo catInfo;
CTextString catName;
TCatArrayIterator iterator(mCategories);
// loop thru categories and add them to the array
while (iterator.Next(catInfo))
{
costInfo.id = catInfo.catID;
// fetch the category name
if (!gDBFile->GetObjectName(id_Category, catInfo.catID, catName))
{
catName = TCS_GetStockString(stockID_MissingItem);
}
TCS_BufferFromText(costInfo.catName, catName);
// create an item array
costInfo.itemArray = NEW TObjectInfoArray;
TCS_FailNILMsg(costInfo.itemArray, TCS_GetErrString(errID_BadArray));
// add it to the array
costArray.Append(costInfo);
}
// finish with 'unallocated' category
costInfo.id = cUnallocatedItem; // rev TCS 2/22/00
TCS_BufferFromText(costInfo.catName, TCS_GetStockString(stockID_Unallocated));
costInfo.itemArray = NEW TObjectInfoArray;
TCS_FailNILMsg(costInfo.itemArray, TCS_GetErrString(errID_BadArray));
// add it to the array
costArray.Append(costInfo);
return true;
}
/*********************************************************************************
FillCostSubcategoryArray TCS 7/30/01
fill a cost array with subcategories in the given category. This struct
is used for job costs.
*********************************************************************************/
Boolean CCategorySystem::FillCostSubcategoryArray(TJobCostCategoryArray &costArray,
const DBid matchCategory) const
{
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
// initialize a cat info struct
SJobCostCategoryInfo costInfo;
InitializeJobCostCategoryInfo(costInfo);
// prepare to iterate
SCatInfo catInfo;
CTextString catName;
TCatArrayIterator iterator(mCategories);
// loop thru categories and add them to the array
while (iterator.Next(catInfo))
{
if (catInfo.catID == matchCategory)
{
TCS_FailNILMsg(catInfo.subcatArray, TCS_GetErrString(errID_BadArray));
TSubCatArrayIterator subIterator(*catInfo.subcatArray);
SSubcatInfo subcatInfo;
while (subIterator.Next(subcatInfo))
{
costInfo.id = subcatInfo.subcatID;
// fetch the subcategory name
if (!gDBFile->GetObjectName(id_Category, subcatInfo.subcatID, catName))
{
catName = TCS_GetStockString(stockID_MissingItem);
}
TCS_BufferFromText(costInfo.catName, catName);
// create an item array
costInfo.itemArray = NEW TObjectInfoArray;
TCS_FailNILMsg(costInfo.itemArray, TCS_GetErrString(errID_BadArray));
// add it to the array
costArray.Append(costInfo);
}
}
}
// finish with 'unallocated' category
costInfo.id = cUnallocatedItem; // rev TCS 2/22/00
TCS_BufferFromText(costInfo.catName, TCS_GetStockString(stockID_Unallocated));
costInfo.itemArray = NEW TObjectInfoArray;
TCS_FailNILMsg(costInfo.itemArray, TCS_GetErrString(errID_BadArray));
// add it to the array
costArray.Append(costInfo);
return true;
}
/*********************************************************************************
FillAllCategoryArray TCS 3/8/00
fill a cost array with all locations. This struct is used for progress billing
when category systems are not being used.
*********************************************************************************/
Boolean CCategorySystem::FillAllCategoryArray(TJobCostReportArray &costArray,
const Boolean includeUnallocated)
{
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
// initialize a struct
SJobCostReportInfo costInfo;
CCategorySystem::InitializeJobCostReportInfo(costInfo);
// fetch an array of all categories
TNameIDArray nameArray;
DB_ListManager::GetNameIDArray(id_Category, &nameArray);
// prepare to iterate
SNameIDInfo info;
TNameIDArrayIterator iterator(nameArray);
// loop thru items and add them to the array
while (iterator.Next(info))
{
costInfo.id = info.id;
// fetch the location name. We can do a direct string
// copy since both buffers are the same length
TCS_StringCopy(costInfo.catName, info.itemName);
costArray.Append(costInfo);
}
// finish with 'unallocated' location
if (includeUnallocated)
{
costInfo.id = cUnallocatedItem; // TCS rev 2/22/00
TCS_BufferFromText(costInfo.catName, TCS_GetStockString(stockID_Unallocated));
costArray.Append(costInfo);
}
return true;
}
/*********************************************************************************
FillProgressArray TCS 9/15/99
fill a progress array with categories. This struct is used for job costs variance
report
*********************************************************************************/
Boolean CCategorySystem::FillProgressArray(TJobCostProgressArray &costArray) const
{
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
// initialize a cat info struct
SJobCostProgressInfo costInfo;
costInfo.contractAmount = 0;
costInfo.percentCompleted = 0;
costInfo.costAmount = 0;
costInfo.valueCompleted = 0;
// prepare to iterate
SCatInfo catInfo;
CTextString catName;
TCatArrayIterator iterator(mCategories);
// loop thru categories and add them to the array
while (iterator.Next(catInfo))
{
costInfo.id = catInfo.catID;
// fetch the category name
if (!gDBFile->GetObjectName(id_Category, catInfo.catID, catName))
{
catName = TCS_GetStockString(stockID_MissingItem);
}
TCS_BufferFromText(costInfo.catName, catName);
costArray.Append(costInfo);
}
// finish with 'unallocated' category
costInfo.id = cUnallocatedItem; // TCS rev 2/22/00
TCS_BufferFromText(costInfo.catName, TCS_GetStockString(stockID_Unallocated));
costArray.Append(costInfo);
return true;
}
/*********************************************************************************
FillDefaultCostArray TCS 9/12/98
fill in a category array when there is no category system
*********************************************************************************/
Boolean CCategorySystem::FillDefaultCostArray(TJobCostCategoryArray &costArray,
const Boolean includeAllCats)
{
// fill in an empty struct
SJobCostCategoryInfo costInfo;
costInfo.equipmentAmount = 0;
costInfo.laborAmount = 0;
costInfo.materialAmount = 0;
costInfo.subcontractorAmount = 0;
costInfo.otherAmount = 0;
costInfo.contractAmount = 0;
costInfo.incomeAmount = 0;
costInfo.changeAmount = 0;
costInfo.itemArray = nil;
if (includeAllCats) // TCS 9/2/00s
{
TNameIDArray allCatArray;
DB_ListManager::GetNameIDArray(id_Category, &allCatArray);
TNameIDArrayIterator iterator(allCatArray);
SNameIDInfo info;
while (iterator.Next(info))
{
costInfo.id = info.id;
// copy the name. We can do a direct string copy
// since both buffers are the same length
TCS_StringCopy(costInfo.catName, info.itemName);
costInfo.itemArray = NEW TObjectInfoArray; // moved TCS 10/31/01
TCS_FailNILMsg(costInfo.itemArray, TCS_GetErrString(errID_BadArray));
// add it to the array
costArray.Append(costInfo);
}
}
else
{
// all we do is an 'unallocated' category
costInfo.id = cUnallocatedItem; // TCS rev 2/22/00
TCS_BufferFromText(costInfo.catName, TCS_GetStockString(stockID_Unallocated));
costInfo.itemArray = NEW TObjectInfoArray; // moved TCS 10/31/01
TCS_FailNILMsg(costInfo.itemArray, TCS_GetErrString(errID_BadArray));
// add it to the array
costArray.Append(costInfo);
}
return true;
}
/*********************************************************************************
FillDefaultProgressArray (static) TCS 9/15/99
fill in a category array when there is no category system
*********************************************************************************/
Boolean CCategorySystem::FillDefaultProgressArray(TJobCostProgressArray &costArray)
{
// prepare to iterate
SJobCostProgressInfo costInfo;
costInfo.contractAmount = 0;
costInfo.costAmount = 0;
costInfo.percentCompleted = 0;
costInfo.valueCompleted = 0;
// all we do is an 'unallocated' category
costInfo.id = cUnallocatedItem; // TCS rev 2/22/00
TCS_BufferFromText(costInfo.catName, TCS_GetStockString(stockID_Unallocated));
costArray.Append(costInfo);
return true;
}
|