Link to: header | source
1 | source
2 | 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.
/*********************************************************************************
FillCatSubcatArray TCS 7/11/02
fill in a report with categories, subcategories and items
*********************************************************************************/
void CEstimate::FillCatSubcatArray(const DBid reportID, TTwoLevelArray *twoLevelArray,
const Boolean hideSoftCosts, CMoney &softCostAmount,
CMoney &hardCostAmount) const
{
if (reportID != id_EstCatSubcatReport)
return;
// loop thru breakdown items and have them fill the array
if (mBreakdownArray.GetCount() > 0)
{
// fill in an array of categories and subcategories
CCategorySystem *catSystem =
TCS_SAFE_CAST(gDBFile->GetOneObject(id_CategorySystem, GetCategorySystem()),
CCategorySystem);
if (catSystem)
{
DB_ObjectWatcher watcher (catSystem);
catSystem->FillCatSubcatArray(reportID, twoLevelArray,
hideSoftCosts, softCostAmount, hardCostAmount);
}
else
CCategorySystem::FillDefaultCatSubcatArray(twoLevelArray);
// loop thru est breakdown items and fill in amounts
TObjectIDArrayIterator iter(mBreakdownArray);
DBid breakdownID;
CCostBreakdownEntry *estBreakdownItem;
while (iter.Next(breakdownID))
{
estBreakdownItem =
TCS_SAFE_CAST(gDBFile->GetOneObject(mBreakdownClassID, breakdownID),
CCostBreakdownEntry);
if (estBreakdownItem)
{
DB_ObjectWatcher watcher(estBreakdownItem);
estBreakdownItem->FillEstCatSubcatInfo(twoLevelArray, hideSoftCosts,
softCostAmount, hardCostAmount);
}
}
}
}
/*********************************************************************************
FillCatItemArray TCS 1/25/03
fill in an array of categories and items
*********************************************************************************/
void CEstimate::FillCatItemArray(const DBid reportID, TReportGroupArray *catArray) const
{
if (reportID != id_EstCatSubcatReport && reportID != id_EstCatReport &&
reportID != id_EstLocationReport)
return;
// loop thru breakdown items and have them fill the array
if (mBreakdownArray.GetCount() > 0)
{
if (reportID == id_EstLocationReport) // TCS 3/10/03
{
CLocationPackage::FillLocationItemArray(catArray);
}
else
{
// fill in an array of categories and subcategories
CCategorySystem *catSystem =
TCS_SAFE_CAST(gDBFile->GetOneObject(id_CategorySystem, GetCategorySystem()),
CCategorySystem);
if (catSystem)
{
DB_ObjectWatcher watcher (catSystem);
catSystem->FillCatItemArray(reportID, catArray);
}
else
CCategorySystem::FillDefaultCatItemArray(catArray);
}
// loop thru est breakdown items and fill in amounts
TObjectIDArrayIterator iterator(mBreakdownArray);
DBid breakdownID;
CBreakdownEntry *breakdownItem;
while (iterator.Next(breakdownID))
{
breakdownItem =
TCS_SAFE_CAST(gDBFile->GetOneObject(mBreakdownClassID, breakdownID),
CBreakdownEntry);
if (breakdownItem)
{
DB_ObjectWatcher watcher(breakdownItem);
breakdownItem->FillCatItemInfo(catArray, 0, false, reportID == id_EstLocationReport);
}
}
}
}
/*********************************************************************************
FillDataReport TCS 9/6/02
fill in a diagnostic table that shows data field values.
*********************************************************************************/
void CEstimate::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);
NeoVersion version = GetVersion();
FillFieldArrayRow(table, stream, "mLocationArray", mLocationArray);
FillFieldArrayRow(table, stream, "mDimensionArray", mDimensionArray);
FillFieldArrayRow(table, stream, "mLocationDimensionArray", mLocationDimensionArray);
FillFieldStringRow(table, stream, tag_name, mName);
FillFieldStringRow(table, stream, tag_address, mAddress);
FillFieldStringRow(table, stream, tag_details, mDetails);
if (version > 1)
FillFieldStringRow(table, stream, tag_scopeofwork, mScopeOfWork, true);
FillFieldObjectIDRow(table, stream, tag_jobtype, mProjectType, id_JobType);
FillFieldObjectIDRow(table, stream, tag_message, mMessage, id_Message);
FillFieldObjectIDRow(table, stream, tag_salesrep, mSalesRep, id_EmployeeAccount);
FillFieldObjectIDRow(table, stream, tag_paymentterm, mPaymentTerm, id_ProjectPaymentTerm);
FillFieldObjectIDRow(table, stream, tag_taxrate, mTaxRate, id_JobSalesTax);
FillFieldObjectIDRow(table, stream, tag_catsystem, mCatSystem, id_CategorySystem);
FillFieldObjectIDRow(table, stream, tag_locationpackage, mLocationPackage, id_LocationPackage);
FillFieldObjectIDRow(table, stream, tag_job, mProject, id_ProjectAccount);
FillFieldObjectIDRow(table, stream, tag_contractid, mContract, id_Contract);
FillFieldObjectIDRow(table, stream, tag_workinghours, mWorkingHours, id_WorkingHours);
FillFieldObjectIDRow(table, stream, tag_workcrew, mWorkCrew, id_WorkCrew);
FillFieldTagRow(table, stream, tag_startdate, cDateSize, mStartDate.GetCString());
FillFieldTagRow(table, stream, tag_finishdate, cDateSize, mFinishDate.GetCString());
FillFieldTagRow(table, stream, tag_grossprice, cMoneySize, mGrossAmount.GetCurrencyString());
FillFieldTagRow(table, stream, tag_projectsize, cMoneySize, mProjectSize.GetNumberString());
FillFieldTagRow(table, stream, tag_taxamount, cMoneySize, mTaxAmount.GetCurrencyString());
FillFieldTagRow(table, stream, tag_adjustpercent, cMoneySize, mAdjustPercent.GetPercentString());
FillFieldObjectIDRow(table, stream, tag_picture, mPictureID, id_Picture); // TCS 7/17/03
FillFieldEnumRow(table, stream, tag_timeperiod, mTimePeriod, MENU_BudgetPeriods);
FillFieldStockRow(table, stream, stockID_Expansion, cCharSize, SInt32(mSpareEnum));
FillFieldObjectIDRow(table, stream, tag_preparedby, mPreparedBy, id_EmployeeAccount);
FillFieldObjectIDRow(table, stream, tag_supervisor, mSupervisor, id_EmployeeAccount);
FillFieldEnumRow(table, stream, tag_status, mStatus, MENU_EstimateStatus);
FillFieldBitRow(table, stream, "mLocationsFromDims" , mLocationsFromDims, true);
FillFieldStockRow(table, stream, stockID_Padding, -7, SInt32(mPadding));
FillEndSafetyTag(table, stream, mEndSafetyTag);
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
CanCopyBreakdown TCS 3/12/02
return whether we can copy a specific breakdown. We don't copy allowances,
bids or purchase orders.
*********************************************************************************/
Boolean CEstimate::CanCopyBreakdown(DB_PersistentObject *breakdown)
{
TCS_FailNILMsg(breakdown, TCS_GetErrString(errID_BadBreakdown));
UInt8 costArea = breakdown->GetCostArea();
switch (costArea)
{
case costtype_allowance:
case costtype_bid:
case costtype_powo:
return false;
default:
return true;
}
}
/*********************************************************************************
CanIncludeCostClass (static) TCS 9/14/98 rev 7/30/01
return whether the given class can be included in a report with the given params
*********************************************************************************/
Boolean CEstimate::CanIncludeCostClass(const UInt8 costClass, const Boolean includeSoft,
const Boolean includeAllowances)
{
switch (costClass)
{
case costtype_assembly:
case costtype_assmlabor: // TCS 11/26/03
case costtype_assmmaterial:
case costtype_bid:
case costtype_subcontractor:
case costtype_labor:
case costtype_material:
case costtype_equipment:
case costtype_unlistedlabor: // TCS 11/4/99
case costtype_unlistedmaterial:
case costtype_unlistedequip:
case costtype_unlistedsub:
case costtype_unlistedother:
case costtype_other:
case costtype_powo:
case costtype_contingencies:
case costtype_tool:
case costtype_obligation:
case costtype_salestax:
case costtype_delivery:
case costtype_changeorder:
return true;
break;
case costtype_allowance: // rev TCS 7/30/01
return includeAllowances;
break;
case costtype_overhead:
case costtype_softcost:
case costtype_profit:
case costtype_commission:
case costtype_percenthard:
case costtype_percenttotal:
case costtype_percentlabor: // TCS 11/8/02
case costtype_percentmaterial:
case costtype_percentsubs:
return includeSoft;
break;
case costtype_reminder:
case costtype_delay:
return false;
break;
default:
TCS_DebugAlert("Oops, bad case in CEstimate::CanIncludeCostClass!");
return false;
break;
}
}
/*********************************************************************************
SetAwardedStatus TCS 2/14/00 rev 12/20/00
award an estimate to a project. We change the status, store a ref to the job,
and also update any allowances, bids, or PO/WO's in our breakdowns.
*********************************************************************************/
DBid CEstimate::SetAwardedStatus(const UInt8 jobClass, const DBid jobID,
const Boolean removeItem, const DBid /*estimateID*/)
{
UInt8 saveType = PrepareViewerDisplay(); // TCS 8/22/00
if (removeItem)
SetToStarterStatus();
else
SetStatus(status_Awarded);
// remember the job TCS 2/29/00 rev 1/4/01
if (removeItem)
{
SetJob(0);
SetJobClass(0);
}
else
{
SetJob(jobID);
SetJobClass(jobClass);
}
// loop thru breakdowns and update any allowances, bids, purchase orders
if (mBreakdownArray.GetCount() > 0)
{
TObjectIDArrayIterator iterator(mBreakdownArray);
DBid breakdownID;
CCostBreakdownEntry *breakdownItem;
while (iterator.Next(breakdownID))
{
breakdownItem =
TCS_SAFE_CAST(gDBFile->GetOneObject(mBreakdownClassID, breakdownID),
CCostBreakdownEntry);
if (breakdownItem)
{
DB_ObjectWatcher watcher(breakdownItem);
breakdownItem->SetAwardedStatus(jobClass, jobID, removeItem, GetDBID());
}
}
}
MakeDirty();
// update the display TCS 3/21/00 rev TCS 10/23/00
UpdateViewerDisplay(saveType);
return 0; // return value is not important (it's there only for bids)
}
/*********************************************************************************
SetCompletedStatus TCS 12/22/00
the project has been completed. Deal with the change.
*********************************************************************************/
void CEstimate::SetCompletedStatus(const Boolean removeItem)
{
UInt8 saveType = PrepareViewerDisplay(); // TCS 8/22/00
if (removeItem)
SetStatus(status_Awarded);
else
SetStatus(status_Completed);
// loop thru breakdowns and update any allowances, bids, purchase orders
if (mBreakdownArray.GetCount() > 0)
{
TObjectIDArrayIterator iterator(mBreakdownArray);
DBid breakdownID;
CCostBreakdownEntry *breakdownItem;
while (iterator.Next(breakdownID))
{
breakdownItem =
TCS_SAFE_CAST(gDBFile->GetOneObject(mBreakdownClassID, breakdownID),
CCostBreakdownEntry);
if (breakdownItem)
{
DB_ObjectWatcher watcher(breakdownItem);
breakdownItem->SetCompletedStatus(removeItem);
}
}
}
MakeDirty();
// update the display TCS 3/21/00 rev TCS 10/23/00
UpdateViewerDisplay(saveType);
}
/*********************************************************************************
UpdateNetPrice TCS 12/13/00
recalculate the net amount after a change in gross price. Use this when
the gross price is changed remotely, while this object is not in a viewer.
This is the object-based equivalent to RecalcAmountWithTax in the viewers.
*********************************************************************************/
void CEstimate::UpdateNetAmount()
{
mTaxAmount = CJobSalesTax::CalculateSalesTaxAmount(mTaxRate, mGrossAmount); // rev TCS 7/23/01
mAmount = mGrossAmount + mTaxAmount;
MakeDirty();
}
/*********************************************************************************
UpdateLineItem TCS 9/6/00 rev 2/11/03
a bid, allowance or PO has changed. Need to change the breakdown and totals
*********************************************************************************/
void CEstimate::UpdateLineItem(const UInt8 costType, const DBid bidID, const CMoney &inAmount,
const CMoney &laborHours, const CMoney &crewSize, const Boolean perUnit)
{
TObjectIDArrayIterator iterator(mBreakdownArray);
DBid breakdownID,
breakdownBidID;
CCostBreakdownEntry *breakdown;
UInt8 costArea;
CMoney oldCost,
oldQuantity;
UInt8 saveSuccess = PrepareViewerDisplay(); // TCS 12/13/00
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
while (iterator.Next(breakdownID))
{
// fetch the breakdown object
breakdown = TCS_SAFE_CAST(gDBFile->GetOneObject(mBreakdownClassID, breakdownID),
CCostBreakdownEntry);
if (breakdown)
{
DB_ObjectWatcher watcher(breakdown);
costArea = breakdown->GetCostArea();
if (costArea == costType)
{
breakdownBidID = breakdown->GetCostItemID();
if (breakdownBidID == bidID)
{
// we found the bid
oldQuantity = breakdown->GetQuantity();
oldCost = breakdown->GetAmount();
if (perUnit)
{ // it's a per unit finished TCS 12/13/00
breakdown->SetUnitCost(inAmount);
breakdown->SetAmount(oldQuantity * inAmount);
mGrossAmount += (oldQuantity * inAmount - oldCost);
}
else
{
breakdown->SetUnitCost(inAmount);
breakdown->SetQuantity(1);
breakdown->SetAmount(inAmount);
mGrossAmount += (inAmount - oldCost);
UpdateNetAmount();
}
breakdown->SetHoursPerUnit(laborHours); // TCS 2/11/03
breakdown->SetCrewSize(crewSize);
MakeDirty();
}
}
}
}
UpdateViewerDisplay(saveSuccess); // TCS 12/13/00
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
DimensionIsLocked (static) TCS split 10/18/01
return whether the given dimension is locked in the given array. We make
this static so it can be used by calculators.
*********************************************************************************/
Boolean CEstimate::DimensionIsLocked(const TagType tag, TDimensionArray dimensionArray)
{
TDimensionArrayIterator iterator(dimensionArray);
SDimensionInfo info;
while (iterator.Next(info))
{
if (info.tag == tag)
return info.locked;
}
// if the dimension is not stored yet, it must be locked
return true;
}
/*********************************************************************************
DimensionIsLocked TCS 1/31/01
return whether the given dimension is locked here
*********************************************************************************/
Boolean CEstimate::DimensionIsLocked(const TagType tag) const
{
return DimensionIsLocked(tag, mDimensionArray);
}
/*********************************************************************************
GetDimensionInfo (static) TCS 10/18/01
return the dimension info for the given tag from the given dimension array.
We make this static so it can be used by calculators.
*********************************************************************************/
SDimensionInfo CEstimate::GetDimensionInfo(const TagType tag, TDimensionArray &dimensionArray)
{
TDimensionArrayIterator iterator(dimensionArray);
SDimensionInfo info;
// loop thru the data in the array, and fetch a struct if it's there
while (iterator.Next(info))
{
if (info.tag == tag)
return info;
}
// if we got this far, the item is not in the array yet, so let's fill in
// a value for it
info.tag = tag;
info.value = 0;
info.location = 0;
info.locked = true;
info.dirty = true;
info.spareByte = 0;
dimensionArray.Append(info); // TCS 1/1/02
return info;
}
/*********************************************************************************
LocationDimensionIsLocked (static) TCS split 11/5/01
return whether the given dimension is locked here
*********************************************************************************/
Boolean CEstimate::LocationDimensionIsLocked(const TagType tag, const UInt8 locationIndex,
TDimensionArray locDimensionArray)
{
TDimensionArrayIterator iterator(locDimensionArray);
SDimensionInfo info;
while (iterator.Next(info))
{
if (info.tag == tag && info.location == locationIndex)
return info.locked;
}
// if we got this far, it must be locked
return true;
}
/*********************************************************************************
LocationDimensionIsLocked TCS 8/24/01
return whether the given dimension is locked here
*********************************************************************************/
Boolean CEstimate::LocationDimensionIsLocked(const TagType tag, const UInt8 locationIndex) const
{
return LocationDimensionIsLocked(tag, locationIndex, mLocationDimensionArray);
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
GetDimensionValue (static) TCS 10/18/01
return the dimension amount for the given tag from the given dimension array.
We make this static so it can be used by calculators.
*********************************************************************************/
CMoney CEstimate::GetDimensionValue(const TagType tag, const TDimensionArray &dimensionArray)
{
TDimensionArrayIterator iterator(dimensionArray);
SDimensionInfo info;
while (iterator.Next(info))
{
if (info.tag == tag)
return info.value;
}
// if we got this far, the value is not stored in the array, so
// we fetch the suggested amount from the dimension object
return CDimension::GetSuggestedAmount(tag);
}
/*********************************************************************************
GetDimensionValue TCS 1/31/01 rev 10/18/01
return the dimension amount for the given tag
*********************************************************************************/
CMoney CEstimate::GetDimensionValue(const TagType tag) const
{
return GetDimensionValue(tag, mDimensionArray);
}
/*********************************************************************************
GetLocationDimensionValue (static) TCS 11/3/01
return the dimension amount for the given tag and location from the given location
dimension array
*********************************************************************************/
CMoney CEstimate::GetLocationDimensionValue(const TagType tag, const TDimensionArray &dimensionArray,
const UInt8 locationID)
{
TDimensionArrayIterator iterator(dimensionArray);
SDimensionInfo info;
while (iterator.Next(info))
{
if (info.tag == tag && info.location == locationID)
return info.value;
}
// if we got this far, the value is not stored in the array, so
// we fetch the suggested amount from the dimension object
return CDimension::GetSuggestedAmount(tag);
}
/*********************************************************************************
GetLocationDimensionValue TCS 5/11/01
return the dimension amount for the given tag
*********************************************************************************/
CMoney CEstimate::GetLocationDimensionValue(const TagType tag, const UInt8 locationID) const
{
return GetLocationDimensionValue(tag, mLocationDimensionArray, locationID);
}
/*********************************************************************************
GetLocationDimensionInfo (static) TCS 10/18/01
return the dimension info for the given tag from the given location dimension
array and location id. We make this static so it can be used by calculators.
*********************************************************************************/
SDimensionInfo CEstimate::GetLocationDimensionInfo(const TagType tag, TDimensionArray &dimensionArray,
const UInt8 locationID)
{
TDimensionArrayIterator iterator(dimensionArray);
SDimensionInfo info;
// loop thru the data in the array, and fetch a struct if it's there
while (iterator.Next(info))
{
if (info.tag == tag && info.location == locationID)
return info;
}
// if we got this far, the item is not stored in the array yet. We'd better add it
info.tag = tag;
info.value = 0;
info.location = locationID;
info.locked = true; // bugfix TCS 1/1/02
info.dirty = true;
info.spareByte = 0;
dimensionArray.Append(info); // TCS 1/1/02
return info;
}
/*********************************************************************************
GetModifierAmount TCS 9/3/02
get the modifier amount for an assembly. We need to fetch the modifier ID
from the assembly and then retrieve that dimension amount
*********************************************************************************/
CMoney CEstimate::GetModifierAmount(const DBid assemblyID) const
{
if (assemblyID)
{
CAssembly *assembly = TCS_SAFE_CAST(gDBFile->GetOneObject(id_Assembly, assemblyID),
CAssembly);
if (assembly)
{
DB_ObjectWatcher watcher(assembly);
DBClass modifierClass = assembly->GetMaterialModifierClass();
DBid modifierID = assembly->GetMaterialModifierID();
if (modifierID && modifierClass)
{
TagType modifierTag = CCalculatorList::GetCalculatorTag(modifierClass, modifierID);
return GetDimensionValue(modifierTag);
}
}
}
// if we get this far there is no modifier
return 0;
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
SetDimensionValue (static) TCS split 10/18/01
set the dimension amount for the given tag in the given array. We make
this static so it can be easily used by calculators.
*********************************************************************************/
void CEstimate::SetDimensionValue(const TagType tag, const CMoney &inAmount,
const Boolean locked, TDimensionArray &dimensionArray)
{
TDimensionArrayIterator iterator(dimensionArray);
SDimensionInfo info;
while (iterator.Next(info))
{
if (info.tag == tag)
{
info.value = inAmount;
info.locked = locked; // bugfix TCS 8/24/01
info.dirty = false; // TCS 1/1/02
info.location = 0;
info.spareByte = 0;
dimensionArray.AssignItemAt(iterator.GetCurrentIndex(), info);
return;
}
}
// item is not in the array yet, so append it
info.tag = tag;
info.value = inAmount;
info.locked = locked;
dimensionArray.Append(info);
}
/*********************************************************************************
SetDimensionValue TCS 1/31/01
set the dimension amount for the given tag
*********************************************************************************/
void CEstimate::SetDimensionValue(const TagType tag, const CMoney &inAmount, const Boolean locked)
{
if (IsInDatabase())
TCS_TokenErrorAlert(errID_BadLengthChange, DB_ClassDescriptor::GetClassName(GetDBClassID()));
else
{
SetDimensionValue(tag, inAmount, locked, mDimensionArray);
MakeDirty(); // TCS 4/8/04
}
}
/*********************************************************************************
SetDimensionsDirty TCS 1/1/02
turn on the dirty bit for all stored dimensions.
*********************************************************************************/
void CEstimate::SetDimensionsDirty(const Boolean inValue)
{
TCS_ASSERTMsg(!IsInDatabase(), "Oops, SetDimensionsDirty called while in database!");
TDimensionArrayIterator iterator(mDimensionArray);
SDimensionInfo info;
while (iterator.Next(info))
{
info.dirty = inValue;
mDimensionArray.AssignItemAt(iterator.GetCurrentIndex(), info);
}
MakeDirty();
}
/*********************************************************************************
SetLocationsDirty TCS 1/1/02
turn on the dirty bit for all stored dimensions in the given location
*********************************************************************************/
void CEstimate::SetLocationsDirty(const UInt8 locationID, const Boolean inValue)
{
TCS_ASSERTMsg(!IsInDatabase(), "Oops, SetLocationDirty called while in database!");
TDimensionArrayIterator iterator(mLocationDimensionArray);
SDimensionInfo info;
while (iterator.Next(info))
{
if (info.location == locationID)
{
info.dirty = inValue;
mLocationDimensionArray.AssignItemAt(iterator.GetCurrentIndex(), info);
}
}
MakeDirty();
}
/*********************************************************************************
SetLocationDimensionValue (static) TCS split 11/5/01
set the location dimension amount for the given tag in the given array
*********************************************************************************/
void CEstimate::SetLocationDimensionValue(const TagType tag, const UInt8 locationID,
const CMoney &inAmount, const Boolean locked,
TDimensionArray &dimensionArray)
{
TDimensionArrayIterator iterator(dimensionArray);
SDimensionInfo info;
while (iterator.Next(info))
{
if (info.tag == tag && info.location == locationID)
{
info.value = inAmount;
info.locked = locked;
info.dirty = false;
dimensionArray.AssignItemAt(iterator.GetCurrentIndex(), info);
return;
}
}
// item is not in the array yet, so fill in a struct and append it
info.location = locationID;
info.spareByte = 0;
info.locked = locked;
info.tag = tag;
info.value = inAmount;
dimensionArray.Append(info);
}
/*********************************************************************************
SetLocationDimensionValue TCS 5/11/01
set the location dimension amount for the given tag
*********************************************************************************/
void CEstimate::SetLocationDimensionValue(const TagType tag, const UInt8 locationID,
const CMoney &inAmount, const Boolean locked)
{
if (IsInDatabase())
{
TCS_TokenErrorAlert(errID_BadLengthChange, DB_ClassDescriptor::GetClassName(GetDBClassID()));
}
else
{
DBClass calcClass = CCalculatorList::GetCalculatorClassID(tag);
if (calcClass == id_LocationDimension || calcClass == id_CalcLocation)
{
SetLocationDimensionValue(tag, locationID, inAmount, locked, mLocationDimensionArray);
}
else
{
SetDimensionValue(tag, inAmount, locked, mDimensionArray); // rev TCS 1/1/02
}
MakeDirty(); // TCS 4/8/04
}
}
/*********************************************************************************
SetDimensionArray TCS 6/7/03
replace the dimension array. This should happen only when the estimate
is not in the database
*********************************************************************************/
void CEstimate::SetDimensionArray(const TDimensionArray &inArray)
{
if (IsInDatabase() && !gIsClient)
{
TCS_TokenErrorAlert(errID_BadLengthChange, DB_ClassDescriptor::GetClassName(GetDBClassID()));
}
else
{
mDimensionArray = inArray;
}
}
/*********************************************************************************
SetLocationDimensionArray TCS 6/7/03
replace the location dimension array. This should happen only when the estimate
is not in the database
*********************************************************************************/
void CEstimate::SetLocationDimensionArray(const TDimensionArray &inArray)
{
if (IsInDatabase() && !gIsClient)
{
TCS_TokenErrorAlert(errID_BadLengthChange, DB_ClassDescriptor::GetClassName(GetDBClassID()));
}
else
{
mLocationDimensionArray = inArray;
}
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
GetNthLocationName TCS 4/13/01
return the Nth location name.
*********************************************************************************/
CTextString CEstimate::GetNthLocationName(const UInt8 index, const Boolean isSorted) const
{
SNameIDInfo info;
CTextString outName;
if (isSorted)
{
TNameIDArray nameArray = mLocationArray;
nameArray.SortWithComparator(NEW CListNameComparator);
if (nameArray.FetchItemAt(index, info) != LArray::index_Bad)
outName = CTextString(info.itemName);
else
outName = TCS_GetStockString(stockID_MissingItem);
}
else if (mLocationArray.FetchItemAt(index, info) != LArray::index_Bad)
outName = CTextString(info.itemName);
else
outName = TCS_GetStockString(stockID_MissingItem);
return outName;
}
/*********************************************************************************
GetNthLocationID TCS 4/13/01
return the Nth location id.
*********************************************************************************/
DBid CEstimate::GetNthLocationID(const UInt8 index, const Boolean isSorted) const
{
SNameIDInfo info;
if (isSorted)
{
TNameIDArray nameArray = mLocationArray;
nameArray.SortWithComparator(NEW CListNameComparator);
if (nameArray.FetchItemAt(index, info) != LArray::index_Bad)
return info.id;
}
else if (mLocationArray.FetchItemAt(index, info) != LArray::index_Bad)
return info.id;
return 0;
}
/*********************************************************************************
GetLocationIndex TCS 4/13/01
return the index position of the location with the given name.
*********************************************************************************/
UInt8 CEstimate::GetLocationIndex(const CTextString inName, const Boolean isSorted) const
{
TNameIDArray nameArray = mLocationArray;
if (isSorted)
nameArray.SortWithComparator(NEW CListNameComparator);
TNameIDArrayIterator iterator(nameArray);
SNameIDInfo info;
CTextString arrayName;
while (iterator.Next(info))
{
arrayName = CTextString(info.itemName);
if (arrayName == inName)
return iterator.GetCurrentIndex();
}
return 0;
}
/*********************************************************************************
GetLocationIndex TCS 4/13/01
return the index position of the location with the given id.
*********************************************************************************/
UInt8 CEstimate::GetLocationIndex(const DBid inID, const Boolean isSorted) const
{
TNameIDArray nameArray = mLocationArray;
if (isSorted)
nameArray.SortWithComparator(NEW CListNameComparator);
TNameIDArrayIterator iterator(nameArray);
SNameIDInfo info;
while (iterator.Next(info))
{
if (inID == info.id)
return iterator.GetCurrentIndex();
}
return 0;
}
/*********************************************************************************
GetLocationName TCS 7/10/01
return the name of the location with the given id.
*********************************************************************************/
CTextString CEstimate::GetLocationName(const DBid inID) const
{
TNameIDArrayIterator iterator(mLocationArray);
SNameIDInfo info;
while (iterator.Next(info))
{
if (inID == info.id)
return CTextString(info.itemName);
}
// if we got this far, the dimension doesn't exist
return TCS_GetStockString(stockID_MissingItem);
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
AddLocation TCS 4/11/01 rev TCS 8/21/03
add a location
*********************************************************************************/
void CEstimate::AddLocation(const CTextString locationName, const DBid locationID)
{
// this method changes the object length, so it would be a serious
// error to call it on an object that is still in the database
if (IsInDatabase())
TCS_TokenErrorAlert(errID_BadLengthChange, DB_ClassDescriptor::GetClassName(GetDBClassID()));
SNameIDInfo info;
DBid nextID = locationID;
Boolean canAdd = true;
// check existing locations for duplicates, and for the next
// available ID number
TNameIDArrayIterator iterator(mLocationArray);
while (iterator.Next(info))
{
// is this location already there? TCS 8/21/03
if (locationName == CTextString(info.itemName))
{
canAdd = false;
break;
}
// check the ID
if (locationID)
{
// importing, check for duplicate ID's TCS 8/21/03
if (info.id == locationID)
{
canAdd = false;
break;
}
}
else if (info.id > nextID)
{
// new item, fetch the highest existing number
nextID = info.id;
}
}
// fill in values
if (canAdd)
{
TCS_BufferFromText(info.itemName, locationName);
if (locationID)
info.id = locationID;
else
info.id = nextID + 1;
// add to the location array
mLocationArray.Append(info);
}
}
/*********************************************************************************
RenameLocation TCS 4/11/01
rename a location
*********************************************************************************/
void CEstimate::RenameLocation(const UInt8 index, const CTextString locationName)
{
// this method changes the object length, so it would be a serious
// error to call it on an object that is still in the database
if (IsInDatabase())
TCS_TokenErrorAlert(errID_BadLengthChange, DB_ClassDescriptor::GetClassName(GetDBClassID()));
SNameIDInfo info;
// sort the location array rev TCS 11/28/01
CListNameComparator *comparator = NEW CListNameComparator;
TCS_FailNILMsg(comparator, TCS_GetErrString(errID_BadComparator));
TCS_TRY
{
mLocationArray.SetComparator(comparator, cDontDeleteComparator);
mLocationArray.Sort();
if (mLocationArray.FetchItemAt(index, info))
{
TCS_BufferFromText(info.itemName, locationName);
mLocationArray.AssignItemAt(index, info);
}
else
TCS_DebugAlert("Oops, bad index in CEstimate::RenameLocation!");
mLocationArray.Sort();
}
TCS_CATCH {}
mLocationArray.ClearComparator(comparator);
}
/*********************************************************************************
DeleteLocation TCS 4/13/01
delete the location at the given menu index
*********************************************************************************/
void CEstimate::DeleteLocation(const UInt8 index)
{
// this method changes the object length, so it would be a serious
// error to call it on an object that is still in the database
if (IsInDatabase())
TCS_TokenErrorAlert(errID_BadLengthChange, DB_ClassDescriptor::GetClassName(GetDBClassID()));
mLocationArray.SortWithComparator(NEW CListNameComparator); // rev TCS 11/28/01
SNameIDInfo info;
if (mLocationArray.FetchItemAt(index, info))
{
mLocationArray.RemoveItemAt(index);
// we should also remove any stored dimension values for this location
TDimensionArrayIterator iterator(mLocationDimensionArray);
SDimensionInfo dimInfo;
while (iterator.Next(dimInfo))
{
if (dimInfo.location == info.id)
mLocationDimensionArray.RemoveItemAt(iterator.GetCurrentIndex());
}
CalculateLocationDimensions();
}
else
TCS_DebugAlert("Oops, bad index in CEstimate::DeleteLocation!");
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
HandleDimensionChanged TCS 10/17/01
a dimension has changed- we need to reset its value in the stored array,
and update any other values that depend on it
*********************************************************************************/
CMoney CEstimate::HandleDimensionChanged(const TagType fieldTag, const CMoney &inValue,
const MessageT source)
{
// sanity check
TCS_ASSERTMsg(!IsInDatabase(), TCS_GetErrString(errID_BadLengthChange));
// first update the stored value
if (source == msg_PadlockOpened)
{
SetDimensionValue(fieldTag, inValue, false);
return inValue; // no need for further action
}
else if (source == msg_PadlockClosed)
{
SetDimensionValue(fieldTag, inValue, true);
}
else if (source == msg_EditFieldChanged || source == msg_PopupClicked ||
source == msg_CheckboxChanged)
{
SetDimensionValue(fieldTag, inValue, false);
}
else
{
TCS_DebugAlert("Oops, bad source in CEstimate::HandleDimensionChange!");
return inValue;
}
CMoney outValue = inValue;
// before we update calculators, set the dirty bit in all stored
// calculator values (since we don't know which ones will be affected
// by this change) TCS 1/1/02
SetDimensionsDirty();
// spin the cursor once
CCursorSpinner spinner; // TCS 1/1/02
// now pass it along to the calculator, so it can update
// any calculated values that depend on this value
DBClass calcClass = CCalculatorList::GetCalculatorClassID(fieldTag);
DBid calcID = CCalculatorList::GetCalculatorItemID(fieldTag);
DB_PersistentObject *calculator = gDBFile->GetOneObject(calcClass, calcID);
if (calculator)
{
DB_ObjectWatcher watcher(calculator);
if (source == msg_PadlockClosed)
outValue = calculator->GetCalcDimensionValue(mDimensionArray, mLocationDimensionArray);
calculator->UpdateDependentDimensions(mDimensionArray, mLocationDimensionArray);
}
else
ReportMissingObject(calcClass, calcID);
return outValue;
}
/*********************************************************************************
HandleLocationDimensionChanged TCS 10/29/01
a location dimension has changed- we need to reset its value in the stored array,
and update any other values that depend on it
*********************************************************************************/
CMoney CEstimate::HandleLocationDimensionChanged(const TagType fieldTag, const UInt8 locationID,
const CMoney &inValue, const MessageT source)
{
// sanity check
TCS_ASSERTMsg(!IsInDatabase(), TCS_GetErrString(errID_BadLengthChange));
if (source == msg_PadlockOpened)
{
// if a padlock was opened, all we need to do is reset the locked bit
SetDimensionValue(fieldTag, inValue, false);
// no need for any further action
return inValue;
}
else if (source == msg_PadlockClosed)
{
SetLocationDimensionValue(fieldTag, locationID, inValue, true);
}
else if (source == msg_EditFieldChanged || source == msg_PopupClicked ||
source == msg_CheckboxChanged)
{
SetLocationDimensionValue(fieldTag, locationID, inValue, false);
}
else
{
TCS_DebugAlert("Oops, bad source in CEstimate::HandleLocationDimensionChanged!");
return inValue;
}
CMoney outValue = inValue;
// before we update calculators, set the dirty bit in all stored
// calculator values for this location. We also mark regular calculators
// for an update TCS 1/1/02
SetLocationsDirty(locationID);
SetDimensionsDirty();
// spin the cursor once
CCursorSpinner spinner; // TCS 1/1/02
// now pass it along to the calculator, so it can update
// any calculated values that depend on this value
DBClass calcClass = CCalculatorList::GetCalculatorClassID(fieldTag);
DBid calcID = CCalculatorList::GetCalculatorItemID(fieldTag);
DB_PersistentObject *calculator = gDBFile->GetOneObject(calcClass, calcID);
if (calculator)
{
DB_ObjectWatcher watcher(calculator);
if (source == msg_PadlockClosed)
outValue = calculator->GetCalcLocationValue(mDimensionArray, mLocationDimensionArray, locationID);
calculator->UpdateDependentLocations(mDimensionArray, mLocationDimensionArray, locationID);
}
else
ReportMissingObject(calcClass, calcID);
return outValue;
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
CalculateLocationDimensions TCS 4/13/01
recalculate all dimensions that depend on locations
*********************************************************************************/
void CEstimate::CalculateLocationDimensions()
{
TCS_SysBeep();
}
|