Link to: header | source
1 | source
2 | source 3 | transactions
directory | estimating info
Copyright Turtle Creek Software 1996-2006. All Rights Reserved.
Source Code
This class manages estimating for the Goldenseal
estimating software,
project estimating software
and construction estimating software.
/*********************************************************************************
PostNewRecord TCS 11/21/03
post info for a new record
*********************************************************************************/
void CEstimate::PostNewRecord(const UInt8 creationType)
{
PostUseCount(id_JobType, mProjectType);
PostUseCount(id_Message, mMessage);
PostUseCount(id_EmployeeAccount, mSalesRep);
PostUseCount(id_ProjectPaymentTerm, mPaymentTerm);
PostUseCount(id_JobSalesTax, mTaxRate);
PostUseCount(id_CategorySystem, mCatSystem);
PostUseCount(id_LocationPackage, mLocationPackage);
PostUseCount(id_WorkingHours, mWorkingHours);
PostUseCount(id_WorkCrew, mWorkCrew);
// let the superclass do any posting
THE_SUPERCLASS::PostNewRecord(creationType);
}
/*********************************************************************************
PostDeletion TCS 11/21/03
post info from a deleted record
*********************************************************************************/
void CEstimate::PostDeletion(const Boolean postAudit)
{
PostUseCount(id_JobType, mProjectType, cRemoveItem);
PostUseCount(id_Message, mMessage, cRemoveItem);
PostUseCount(id_EmployeeAccount, mSalesRep, cRemoveItem);
PostUseCount(id_ProjectPaymentTerm, mPaymentTerm, cRemoveItem);
PostUseCount(id_JobSalesTax, mTaxRate, cRemoveItem);
PostUseCount(id_CategorySystem, mCatSystem, cRemoveItem);
PostUseCount(id_LocationPackage, mLocationPackage, cRemoveItem);
PostUseCount(id_WorkingHours, mWorkingHours, cRemoveItem);
PostUseCount(id_WorkCrew, mWorkCrew, cRemoveItem);
// let the superclass do any posting
THE_SUPERCLASS::PostDeletion(postAudit);
}
/*********************************************************************************
PostRecordActivated TCS 3/8/00
post a newly created or activated transaction
*********************************************************************************/
void CEstimate::PostRecordActivated(const UInt8 creationType)
{
if (!WasJustImported()) // TCS rev 2/14/01
PostEstimate();
UpdateContactAccount();
// let the superclass do any posting
THE_SUPERCLASS::PostRecordActivated(creationType);
}
/*********************************************************************************
PostRecordCancelled TCS 3/8/00
post a deleted or voided transaction
*********************************************************************************/
void CEstimate::PostRecordCancelled(const UInt8 cancelType)
{
PostEstimate(cRemoveItem);
UpdateContactAccount(cRemoveItem);
// let the superclass do any posting
THE_SUPERCLASS::PostRecordCancelled(cancelType);
}
/*********************************************************************************
PostRecordChanging TCS 3/8/00
a record will be changing. Post the change.
*********************************************************************************/
void CEstimate::PostRecordChanging(const Boolean accountChanging, const Boolean jobChanging)
{
PostEstimate(cRemoveItem);
UpdateContactAccount(cRemoveItem);
PostUseCount(id_JobType, mProjectType, cRemoveItem); // TCS 11/21/03
PostUseCount(id_Message, mMessage, cRemoveItem);
PostUseCount(id_EmployeeAccount, mSalesRep, cRemoveItem);
PostUseCount(id_ProjectPaymentTerm, mPaymentTerm, cRemoveItem);
PostUseCount(id_JobSalesTax, mTaxRate, cRemoveItem);
PostUseCount(id_CategorySystem, mCatSystem, cRemoveItem);
PostUseCount(id_LocationPackage, mLocationPackage, cRemoveItem);
PostUseCount(id_WorkingHours, mWorkingHours, cRemoveItem);
PostUseCount(id_WorkCrew, mWorkCrew, cRemoveItem);
// let the superclass have a crack
THE_SUPERCLASS::PostRecordChanging(accountChanging, jobChanging);
}
/*********************************************************************************
PostRecordChanged TCS 3/8/00
a record has changed. Post it.
*********************************************************************************/
void CEstimate::PostRecordChanged(const CMoney &oldAmount, const Boolean accountChanged,
const Boolean jobChanged)
{
PostEstimate();
UpdateContactAccount();
PostUseCount(id_JobType, mProjectType); // TCS 11/21/03
PostUseCount(id_Message, mMessage);
PostUseCount(id_EmployeeAccount, mSalesRep);
PostUseCount(id_ProjectPaymentTerm, mPaymentTerm);
PostUseCount(id_JobSalesTax, mTaxRate);
PostUseCount(id_CategorySystem, mCatSystem);
PostUseCount(id_LocationPackage, mLocationPackage);
PostUseCount(id_WorkingHours, mWorkingHours);
PostUseCount(id_WorkCrew, mWorkCrew);
THE_SUPERCLASS::PostRecordChanged(oldAmount, accountChanged, jobChanged);
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
PostEstimate TCS 3/8/00
an estimate has changed. Post it. We fill in the estimate field in the job
account.
*********************************************************************************/
void CEstimate::PostEstimate(const Boolean removeItem)
{
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
DB_Account *job =
TCS_SAFE_CAST(gDBFile->GetOneObject(mMainAccountClass, mMainAccount),
DB_Account);
if (job)
{
DB_ObjectWatcher watcher(job);
DBid estimateID = job->GetEstimateID();
DBid thisID = GetDBID();
if (removeItem)
{
job->SetEstimateID(0);
}
else if (mMainAccountClass != id_CustomerAccount && estimateID && // rev TCS 9/1/00
estimateID != thisID)
{
if (TCS_YesNoDialog(TCS_GetMsgString(msgID_ReplaceEstimate)))
job->SetEstimateID(thisID);
}
else
{
job->SetEstimateID(GetDBID());
}
}
// use schedule dates to adjust the max/min dates TCS 1/3/03
gDBFile->UpdateEarlyLateDates(mStartDate);
gDBFile->UpdateEarlyLateDates(mFinishDate);
}
/*********************************************************************************
UpdateContactAccount TCS 11/3/02
update contact data in a prospect record. Any class can respond to this,
though currently the only ones that do so are job accounts, cost accounts
and address book records
*********************************************************************************/
void CEstimate::UpdateContactAccount(const Boolean removeItem)
{
DB_PersistentObject *prospect = gDBFile->GetOneObject(mMainAccountClass,
mMainAccount);
if (prospect)
{
DB_ObjectWatcher watcher(prospect);
prospect->UpdateContactInfo(id_Estimate, GetDBID(), removeItem);
}
}
/*********************************************************************************
ReplaceMatchText TCS 3/6/04
replace the match text with a value. We override for the details field to
use specs if it's available.
*********************************************************************************/
void CEstimate::ReplaceMatchText(CTextString &baseString, const CTextString &matchString,
const TagType tag, const Boolean removeReturns,
const Boolean replaceAll) const
{
if (tag == tag_details)
{
if (mScopeOfWork.Length())
DoTextSubstitute(baseString, matchString, mScopeOfWork, removeReturns, replaceAll);
else
DoTextSubstitute(baseString, matchString, mDetails, removeReturns, replaceAll);
}
else
THE_SUPERCLASS::ReplaceMatchText(baseString, matchString, tag, removeReturns,
replaceAll);
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
FinishBreakdownUpdate TCS 8/2/01
we have just entered data into a breakdown. We override to make sure that
item breakdowns get their calculated values updated from the assembly
*********************************************************************************/
void CEstimate::FinishBreakdownUpdate(CBreakdownEntry *breakdown, CBreakdownTable */*table*/)
{
TCS_FailNILMsg(breakdown, TCS_GetErrString(errID_BadBreakdown));
CEstItemBreakdownEntry *entry = TCS_SAFE_CAST(breakdown, CEstItemBreakdownEntry);
if (entry) // bugfix TCS 9/26/01
entry->UpdatePriceBreakdown();
}
/*********************************************************************************
GetJobCatSystem (static)
return the category system for the estimate of the passed id
*********************************************************************************/
DBid CEstimate::GetJobCatSystem(DBid estimateID)
{
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
DB_PersistentObject *estimate = gDBFile->GetOneObject(id_Estimate, estimateID);
if (estimate)
{
DB_ObjectWatcher watcher(estimate);
DBid catSystem = 0;
estimate->GetMemberValue(tag_catsystem, type_objectid, &catSystem);
return catSystem;
}
else
return 0;
//return CJobType::GetJobTypeCatSystem(GetJobType(estimateID));
}/*********************************************************************************
GetJobAccountType (static) renamed TCS 8/11/03
return the job account type id for an estimate
*********************************************************************************/
DBid CEstimate::GetJobAccountType(DBid estimateID)
{
// sanity check
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
// get the estimate
DB_PersistentObject *estimate =
gDBFile->GetOneObject(id_Estimate, estimateID);
if (estimate)
{ // got the estimate, get the job type id
DB_ObjectWatcher watcher(estimate);
DBid jobTypeID;
TCS_ASSERTMsg(estimate->GetMemberValue(tag_accounttype, type_objectid, &jobTypeID),
TCS_GetValueErrString(tag_accounttype));
return jobTypeID;
}
else
return 0;
}
/*********************************************************************************
IsValidBreakdown
return whether the passed breakdown type is valid
*********************************************************************************/
/*Boolean CEstimate::IsValidBreakdown(const UInt8 breakdownType)
{
switch (breakdownType)
{
case breakdown_none:
case breakdown_item:
case breakdown_category:
case breakdown_powo:
//case breakdown_draw:
//case breakdown_time:
return true;
break;
default:
return false;
break;
}
}*/
/*********************************************************************************
IsItemized
return whether this estimate includes any allowance items.
We get that by looking thru breakdown items
*********************************************************************************/
Boolean CEstimate::IsItemized()
{
// first of all, if no breakdowns, we can't have allowances
if (!GetNumBreakdowns())
return false;
if (mBreakdownType == breakdown_estcategory || mBreakdownType == breakdown_estitem)
{
return true;
}
else
return false;
}
/*********************************************************************************
HasRecordLock TCS 1/22/04
return whether this record should be locked. We want to lock the data
fields but not the status popup for some status values
*********************************************************************************/
Boolean CEstimate::HasRecordLock() const
{
if (mStatus == status_Submitted || mStatus == status_Approved)
return true;
else
return THE_SUPERCLASS::HasRecordLock();
}
/*********************************************************************************
HasLockedStatus TCS 4/11/99
certain status types are 'locked', meaning they cause the status menu and
most other fields to be non-user-accessible
*********************************************************************************/
Boolean CEstimate::HasLockedStatus() const
{
UInt8 status = GetStatus();
return (status == status_Awarded ||
status == status_Started ||
status == status_Completed);
}
/*********************************************************************************
HasSubcategories TCS 1/25/03
return whether this account uses subcategories for job costing
*********************************************************************************/
Boolean CEstimate::HasSubcategories() const
{
DBid catSystem = GetCategorySystem();
if (catSystem)
{
CCategorySystem *system =
TCS_SAFE_CAST(gDBFile->GetOneObject(id_CategorySystem, catSystem),
CCategorySystem);
if (system)
{
DB_ObjectWatcher watcher(system);
return system->HasSubcategories();
}
}
// if we get this far, there are no subcats
return false;
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
FindCategory
find the entry in a cost array for a given category
*********************************************************************************/
SInt32 CEstimate::FindCategory(const DBid catID, TJobCostReportArray &costArray) const
{
SJobCostReportInfo catItem;
TJobCostReportArrayIterator catIterator(costArray);
while (catIterator.Next(catItem))
{
if (catItem.id == catID)
return catIterator.GetCurrentIndex();
}
// got here, couldn't find it
return 0;
}
/*********************************************************************************
FindCategory
find the entry in a cost array for a given category
*********************************************************************************/
SInt32 CEstimate::FindCategory(const DBid catID, TJobCostCategoryArray &costArray) const
{
SJobCostCategoryInfo catItem;
TJobCostCategoryArrayIterator catIterator(costArray);
while (catIterator.Next(catItem))
{
if (catItem.id == catID)
return catIterator.GetCurrentIndex();
}
// got here, couldn't find it
return 0;
}
/*********************************************************************************
FindCategory
find the entry in a progress array for a given category
*********************************************************************************/
SInt32 CEstimate::FindCategory(const DBid catID, TJobCostProgressArray &costArray) const
{
SJobCostProgressInfo catItem;
TJobCostProgressArrayIterator catIterator(costArray);
while (catIterator.Next(catItem))
{
if (catItem.id == catID)
return catIterator.GetCurrentIndex();
}
// got here, couldn't find it
return 0;
}
/*********************************************************************************
FillProgressCatArray TCS rev 6/1/02
fill a progress by category or location array with costs from the breakdown
of this estimate
*********************************************************************************/
Boolean CEstimate::FillProgressCatArray(TJobCostReportArray &costArray, const DBid reportID)
{
// let's see if we have breakdowns
if (mBreakdownArray.GetCount() > 0)
{
// if we have breakdowns, we start with an array of categories or locations
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
if (reportID == project_ProgressLocation) // fill in a list of locations TCS 10/4/99 bugfix 11/28/99
{
Boolean useLocationPackage = gDBFile->UseLocationPackages();
DBid packageID = 0;
if (useLocationPackage)
packageID = GetLocationPackage();
// have the location package fill the initial array
if (packageID)
{
CLocationPackage *package = TCS_SAFE_CAST(gDBFile->GetOneObject(id_LocationPackage,
packageID), CLocationPackage);
TCS_FailNILMsg(package, TCS_GetErrString(errID_BadCatSystem));
DB_ObjectWatcher watcher(package);
package->FillLocationArray(costArray);
}
else
{
CLocationPackage::FillAllLocationArray(costArray);
}
}
else // fill in a list of categories
{
Boolean useCatSystem = gDBFile->UseCategorySystems();
DBid catSystemID = 0;
if (useCatSystem)
catSystemID = GetCategorySystem();
// have the category system fill the initial array
if (catSystemID)
{
CCategorySystem *catSystem = TCS_SAFE_CAST(gDBFile->GetOneObject(id_CategorySystem,
catSystemID), CCategorySystem);
TCS_FailNILMsg(catSystem, TCS_GetErrString(errID_BadCatSystem));
DB_ObjectWatcher watcher(catSystem);
catSystem->FillCostReportArray(costArray);
}
else
{
CCategorySystem::FillAllCategoryArray(costArray);
}
}
// whether or not there are items in the list, we also add an 'unallocated' item
SJobCostReportInfo costInfo;
CCategorySystem::InitializeJobCostReportInfo(costInfo);
costInfo.id = cUnallocatedItem; // TCS rev 2/22/00
TCS_BufferFromText(costInfo.catName, TCS_GetStockString(stockID_Unallocated));
costArray.Append(costInfo);
// get the default row, and sanity check
SInt32 defaultIndex = costArray.GetCount();
TCS_FailNILMsg(defaultIndex, TCS_GetErrString(errID_BadArray));
// now let's prepare to iterate thru breakdown items
DBid entryID = 0;
DBid entryClassID = GetBreakdownClassID();
DBid catID;
UInt8 costClass;
CMoney amount, quantity;
SJobCostReportInfo catItem;
SInt32 catIndex;
TObjectIDArrayIterator iterator(mBreakdownArray);
// loop thru breakdown items
while (iterator.Next(entryID))
{
CCostBreakdownEntry *entry =
TCS_SAFE_CAST(gDBFile->GetOneObject(entryClassID, entryID),
CCostBreakdownEntry);
TCS_FailNILMsg(entry, TCS_GetErrString(errID_BadObject));
DB_ObjectWatcher watcher(entry);
// fetch info from the entry
if (reportID == project_ProgressLocation)
catID = entry->GetLocation(); // bugfix TCS 12/22/99
else
catID = entry->GetCategory();
amount = entry->GetAmount();
entry->GetMemberValue(tag_costarea, type_enum, &costClass);
entry->GetMemberValue(tag_quantity, type_number, &quantity); // bugfix TCS 3/15/00
// look for the category
catIndex = FindCategory(catID, costArray);
if (!catIndex)
catIndex = defaultIndex;
// fetch the existing item
costArray.FetchItemAt(catIndex, catItem);
catItem.contractAmount += amount;
switch (costClass)
{
case costtype_assembly: // the assembly allocates the cost TCS 12/22/99
case costtype_assmlabor: // TCS 11/26/03
case costtype_assmmaterial:
{
DBid assemblyID;
assemblyID = entry->GetCostItemID();
CAssembly *assembly =
TCS_SAFE_CAST(gDBFile->GetOneObject(id_Assembly, assemblyID),
CAssembly);
if (assembly)
{
DB_ObjectWatcher watcher(assembly);
assembly->FillCostBreakdown(catItem, quantity);
}
else
catItem.materialAmount += amount; // bugfix TCS 6/1/02
}
break;
case costtype_material:
case costtype_unlistedmaterial:
catItem.materialAmount += amount;
break;
case costtype_labor:
case costtype_unlistedlabor:
catItem.laborAmount += amount;
break;
case costtype_subcontractor:
case costtype_unlistedsub:
catItem.subcontractorAmount += amount;
break;
case costtype_equipment:
case costtype_unlistedequip:
catItem.equipmentAmount += amount;
break;
case costtype_other:
case costtype_unlistedother:
default:
catItem.otherAmount += amount;
break;
}
// assign the value
costArray.AssignItemAt(catIndex, catItem);
}
}
return true;
}
/*********************************************************************************
FillProgressItemArray TCS 6/1/02
fill a progress by item array with costs from the breakdown of this estimate
*********************************************************************************/
Boolean CEstimate::FillProgressItemArray(SProjectInfo &projectInfo)
{
TCS_FailNILMsg(projectInfo.itemArray, TCS_GetErrString(errID_BadArray));
DBid entryID = 0;
DBid entryClassID = GetBreakdownClassID();
TObjectIDArrayIterator iterator(mBreakdownArray);
CTextString itemName;
SProjectItemInfo itemInfo;
CProjectAccount::InitializeProjectItemInfo(itemInfo);
// loop thru breakdown items
while (iterator.Next(entryID))
{
CCostBreakdownEntry *entry =
TCS_SAFE_CAST(gDBFile->GetOneObject(entryClassID, entryID),
CCostBreakdownEntry);
TCS_FailNILMsg(entry, TCS_GetErrString(errID_BadObject));
DB_ObjectWatcher watcher(entry);
itemInfo.contractAmount = entry->GetAmount();
itemInfo.costArea = entry->GetCostArea();
// we skip some items that have no cost TCS 3/31/03
if (itemInfo.costArea == costtype_delay ||
itemInfo.costArea == costtype_tool ||
itemInfo.costArea == costtype_reminder)
{
if (itemInfo.contractAmount.IsZero())
continue;
}
itemInfo.id = entry->GetDBID(); // rev TCS 10/9/02
itemName = entry->GetName();
TCS_BufferFromText(itemInfo.itemName, itemName);
projectInfo.itemArray->Append(itemInfo);
// no need to change the contract amount TCS bugfix 3/31/03
}
return true;
}
/*********************************************************************************
FillContractInfo TCS 9/13/98
fill an existing category cost array with contract info
from this estimate's breakdowns. If a value is passed for catID, we'll
get the subcategory amounts for one category (rev TCS 7/30/01)
*********************************************************************************/
Boolean CEstimate::FillContractInfo(TJobCostCategoryArray &costArray,
const UInt8 breakdownType, const DBid matchCatID,
const Boolean includeSoft)
{
SInt32 defaultIndex = costArray.GetCount();
TCS_FailNILMsg(defaultIndex, TCS_GetErrString(errID_BadArray));
SJobCostCategoryInfo catItem;
// let's see if we have breakdowns.
if (mBreakdownArray.GetCount() > 0)
{
// let's prepare to iterate thru breakdown items
DBid entryID = 0;
DBid entryClassID = GetBreakdownClassID();
DBid catID;
UInt8 costClass;
CMoney amount,
totalAmount = 0;
SInt32 catIndex;
Boolean includeAllowances = !GetPrefsBoolean(id_ExpensePrefs, tag_skipallowances); // TCS 7/30/01
TObjectIDArrayIterator iterator(mBreakdownArray);
while (iterator.Next(entryID)) // loop thru breakdown items
{
CCostBreakdownEntry *entry =
TCS_SAFE_CAST(gDBFile->GetOneObject(entryClassID, entryID),
CCostBreakdownEntry);
TCS_FailNILMsg(entry, TCS_GetErrString(errID_BadObject));
DB_ObjectWatcher watcher(entry);
// fetch info from the entry
entry->GetMemberValue(tag_costarea, type_enum, &costClass);
if (CanIncludeCostClass(costClass, includeSoft, includeAllowances))
{
if (breakdownType == breakdown_location)
entry->GetMemberValue(tag_location, type_objectid, &catID);
else
entry->GetMemberValue(tag_category, type_objectid, &catID);
if (matchCatID) // is this a subcategory array? TCS 7/30/01
{
if (catID != matchCatID)
continue;
else
entry->GetMemberValue(tag_subcategory, type_objectid, &catID);
}
catIndex = FindCategory(catID, costArray);
amount = entry->GetAmount();
if (!catIndex)
catIndex = defaultIndex;
costArray.FetchItemAt(catIndex, catItem);
catItem.contractAmount += amount;
// assign the value
costArray.AssignItemAt(catIndex, catItem);
}
}
}
else if (!matchCatID)
{ // if no breakdown, we put the total contract amount into unallocated row
costArray.FetchItemAt(defaultIndex, catItem);
catItem.contractAmount = mAmount;
// assign the value
costArray.AssignItemAt(defaultIndex, catItem);
}
else
{ // for subcat breakdown, we do nothing if no breakdowns TCS 7/30/01
}
return true;
}
/*********************************************************************************
FillProgressContractInfo TCS 9/15/99 rev TCS 10/10/02
fill an existing progress cost array with contract info
from this estimate's breakdowns
*********************************************************************************/
Boolean CEstimate::FillProgressContractInfo(TJobCostProgressArray &costArray,
const UInt8 breakdownType,
const Boolean includeSoft)
{
SInt32 defaultIndex = costArray.GetCount();
TCS_FailNILMsg(defaultIndex, TCS_GetErrString(errID_BadArray));
SJobCostProgressInfo catItem;
// let's see if we have breakdowns.
if (mBreakdownArray.GetCount() > 0)
{
// let's prepare to iterate thru breakdown items
DBid entryID = 0;
DBid entryClassID = GetBreakdownClassID();
DBid catID;
UInt8 costClass;
CMoney amount;
SInt32 catIndex;
Boolean includeAllowances = false;
TObjectIDArrayIterator iterator(mBreakdownArray);
while (iterator.Next(entryID)) // loop thru breakdown items
{
CCostBreakdownEntry *entry =
TCS_SAFE_CAST(gDBFile->GetOneObject(entryClassID, entryID),
CCostBreakdownEntry);
TCS_FailNILMsg(entry, TCS_GetErrString(errID_BadObject));
DB_ObjectWatcher watcher(entry);
// fetch info from the entry
entry->GetMemberValue(tag_costarea, type_enum, &costClass);
if (CanIncludeCostClass(costClass, includeSoft, includeAllowances))
{
if (breakdownType == breakdown_location)
entry->GetMemberValue(tag_location, type_objectid, &catID);
else
entry->GetMemberValue(tag_category, type_objectid, &catID);
amount = entry->GetAmount();
catIndex = FindCategory(catID, costArray);
if (!catIndex)
catIndex = defaultIndex;
costArray.FetchItemAt(catIndex, catItem);
catItem.contractAmount += amount;
// assign the value
costArray.AssignItemAt(catIndex, catItem);
}
}
}
else // if no breakdown, we put the total contract amount into unallocated row
{
costArray.FetchItemAt(defaultIndex, catItem);
catItem.contractAmount = mAmount;
// assign the value
costArray.AssignItemAt(defaultIndex, catItem);
}
return true;
}
/*********************************************************************************
FillCompareArray TCS 8/1/01
fill estimated values in a job cost comparison array
*********************************************************************************/
void CEstimate::FillCompareArray(TJobCostCompareArray &compareArray,
const DBid reportID)
{
Boolean useSubcats = reportID == id_JobCostSubcatReport;
Boolean useLocations = (reportID == id_JobCostLocationReport || reportID == id_JobCostLocationClassReport);
SJobCostCompareInfo compareInfo;
// let's see if we have breakdowns.
if (mBreakdownArray.GetCount() > 0)
{
// let's prepare to iterate thru breakdown items
DBid entryID = 0;
DBid entryClassID = GetBreakdownClassID();
UInt8 costClass;
CMoney amount;
Boolean includeAllowances = false;
TObjectIDArrayIterator iterator(mBreakdownArray);
TJobCostCompareArrayIterator compareIterator(compareArray);
SInt32 currentIndex;
while (iterator.Next(entryID)) // loop thru breakdown items
{
CCostBreakdownEntry *entry =
TCS_SAFE_CAST(gDBFile->GetOneObject(entryClassID, entryID),
CCostBreakdownEntry);
TCS_FailNILMsg(entry, TCS_GetErrString(errID_BadObject));
DB_ObjectWatcher watcher(entry);
// fetch info from the entry
costClass = entry->GetCostArea();
// we can skip some cost areas
if (costClass == costtype_tool || costClass == costtype_reminder ||
costClass == costtype_delay)
continue;
// start with a zero id. Note that this must be initialized
// within the loop, since each item needs to start at zero
DBid catID = 0; // TCS bugfix 11/26/01
if (useLocations) // TCS 11/7/01
{
catID = entry->GetLocation();
}
else
{
if (useSubcats)
catID = entry->GetSubcategory();
if (!catID)
catID = entry->GetCategory();
}
amount = entry->GetAmount();
// first search for the correct line in the struct.
// if there is no match it'll go in the last item (unallocated)
compareIterator.ResetToStart();
currentIndex = compareArray.GetCount(); // rev TCS 2/10/03
while (compareIterator.Next(compareInfo))
{
if (compareInfo.id == catID)
{
currentIndex = compareIterator.GetCurrentIndex();
break;
}
}
compareArray.FetchItemAt(currentIndex, compareInfo); // bugfix TCS 11/26/01
if (entry->FillJobCostCompareInfo(compareInfo, 0, 0, 0, true))
{
compareArray.AssignItemAt(currentIndex, compareInfo);
}
}
}
else // if no breakdown, put the total contract amount into unallocated row
{
compareArray.FetchLastItem(compareInfo);
compareInfo.estMaterials += GetAmount();
compareArray.AssignToLast(compareInfo);
}
}
|