Link to: header | transactions
directory
Copyright Turtle Creek Software 1996-2006. All Rights Reserved.
Comments
CAllowance
This class manages project allowances for the Goldenseal accounting software,
small business management software, construction
project management software and
construction
accounting software.
This is the class for an allowance. This is a fixed-price item in an estimate.
Goldenseal includes separate allowance billing which collects for the
difference between actual cost and the original allowance.
Allowances allow estimates to be given even when there aren't firm
specifications for some items.
SUPERCLASS = CChangeOrder
Constructor
/*********************************************************************************
constructor
*********************************************************************************/
CAllowance::CAllowance()
{
mConditions = condition_TotalCost;
mCostPerUnit = false;
mEstimate = 0;
mAllowancePadding = 0;
mEndSafetyTag = tag_endsafetytag; // TCS 9/8/02
}
Source Code
/*********************************************************************************
GetFileLength
return the file length used by this object
*********************************************************************************/
NeoSize CAllowance::GetFileLength(const CNeoFormat *aFormat) const
{
return THE_SUPERCLASS::GetFileLength(aFormat) +
cFileLength;
}/*********************************************************************************
GetMemberValue
return the value of the member with the given tag
*********************************************************************************/
Boolean CAllowance::GetMemberValue(const TagType aTag, const TagType aType,
void *aValue) const
{
switch (aTag)
{
case tag_estimate: // TCS 2/14/00
return ConvertObjectIDMember(mEstimate, id_Estimate, aValue, aType);
break;
case tag_projectaccount: // TCS 2/14/00
return ConvertObjectIDMember(mMainAccount, id_ProjectAccount, aValue, aType);
break;
case tag_conditions: // TCS 8/9/02
return ConvertEnumMember(mConditions, MENU_AllowanceConditions, aValue, aType);
break;
case tag_quantity:
return ConvertMember(&mQuantity, type_money, aValue, aType);
break;
case tag_costarea: // we calculate this for item cv's TCS 3/20/99 bugfix 7/26/99
{
UInt8 costArea = costtype_allowance;
return ConvertMember(&costArea, type_enum, aValue, aType);
}
break;
case tag_unitcost:
return ConvertBitFieldMember(mCostPerUnit, aValue, aType);
break;
default:
return THE_SUPERCLASS::GetMemberValue(aTag, aType, aValue);
break;
}
}/*********************************************************************************
SetMemberValue
set the value of the member with the given tag
*********************************************************************************/
Boolean CAllowance::SetMemberValue(const TagType aTag, const TagType aType,
const void *aValue)
{
switch (aTag)
{
case tag_estimate: // TCS 2/14/00
return ConvertDataToObjectID(aValue, aType, &mEstimate, id_Estimate);
break;
case tag_projectaccount: // TCS 2/14/00
return ConvertDataToObjectID(aValue, aType, &mMainAccount, id_ProjectAccount);
break;
case tag_quantity:
return ConvertMember(aValue, aType, &mQuantity, type_money);
break;
case tag_unitcost:
mCostPerUnit = ConvertDataToBitField(aValue, aType);
return true;
break;
default:
return THE_SUPERCLASS::SetMemberValue(aTag, aType, aValue);
break;
}
}/*********************************************************************************
ReadObject
read the persistent object's data in from a stream
*********************************************************************************/
void CAllowance::ReadObject(CNeoStream *aStream, const TagType aTag)
{
TCS_FailNILMsg(aStream, TCS_GetErrString(errID_BadStream));
CNeoDebugImport checker(aStream, this, cCheckTooSmall); // TCS 2/24/00
THE_SUPERCLASS::ReadObject(aStream, aTag);
if (!IsIOValid()) // TCS 2/5/02
return;
/// aStream->ReadChunk(&mQuantity, cFileLength);
mQuantity.ReadFromStream(aStream); // mfs_sa rev 20feb2k3
*((UInt8*)&mQuantity + sizeof(mQuantity)) = aStream->ReadBits(1); // --Bitfield
mAllowancePadding = aStream->ReadChar();
mEstimate = aStream->ReadID();
mEndSafetyTag = aStream->ReadEndSafetyTag(this);
if (!IsValidEndTag(mEndSafetyTag)) // TCS 9/8/02
ReportDamagedObject(GetDBClassID(), GetDBID());
}
/*********************************************************************************
WriteObject
write the persistent object's data to a stream
*********************************************************************************/
void CAllowance::WriteObject(CNeoStream *aStream, const TagType aTag)
{
TCS_FailNILMsg(aStream, TCS_GetErrString(errID_BadStream));
// make sure we have valid data to write TCS 9/8/02
if (!IsValidEndTag(mEndSafetyTag))
{
ReportDamagedObject(GetDBClassID(), GetDBID());
mEndSafetyTag = tag_endsafetytag; // TCS 11/26/02
}
CNeoDebugExport checker(aStream, this, cCheckTooSmall);
THE_SUPERCLASS::WriteObject(aStream, aTag);
///aStream->WriteChunk(&mQuantity, cFileLength);
mQuantity.WriteToStream(aStream); // mfs_sa rev 20feb2k3
aStream->WriteChar(*((UInt8*)&mQuantity + sizeof(mQuantity))); // --Bitfield
aStream->WriteChar(mAllowancePadding);
aStream->WriteID(mEstimate);
aStream->WriteEndSafetyTag(mEndSafetyTag, this);
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
HandleExpenseTrans TCS 12/21/98 rev 1/18/00 rev 10/31/00
add a cost item to our cost total and array
*********************************************************************************/
void CAllowance::HandleExpenseTrans(const CMoney &amount, const CMoney &taxAmount,
const UInt8 classID, const DBid costID,
const Boolean removeIt)
{
// CChangeOrder can handle it
THE_SUPERCLASS::HandleExpenseTrans(amount, taxAmount, classID, costID, removeIt);
}
/*********************************************************************************
HandleEstimateUse TCS 9/7/00
this allowance is now included in an estimate
*********************************************************************************/
void CAllowance::HandleEstimateUse(const DBid estimateID, const CMoney quantity, const Boolean removeIt)
{
UInt8 saveType = PrepareViewerDisplay(); // TCS 9/10/00 rev TCS 10/23/00
if (removeIt)
{
mEstimate = 0;
mQuantity = 0; // TCS 8/9/02
SetToStarterStatus();
}
else
{
mEstimate = estimateID;
mQuantity = quantity;
SetStatus(status_InUse); // TCS 9/10/00
}
MakeDirty();
UpdateViewerDisplay(saveType); // TCS 9/10/00
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
SetAwardedStatus TCS 6/23/00
the estimate that includes this allowances has been awarded to a job.
Mark our status also. We also store the project id.
*********************************************************************************/
DBid CAllowance::SetAwardedStatus(const UInt8 jobClass, const DBid jobID,
const Boolean removeItem, const DBid estimateID)
{
UInt8 saveType = PrepareViewerDisplay(); // TCS 9/10/00 rev TCS 10/23/00
mEstimate = estimateID; // TCS 12/20/00
// update inclusion in the project array
if (jobClass == id_ProjectAccount)
{
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
CProjectAccount *project =
TCS_SAFE_CAST(gDBFile->GetOneObject(id_ProjectAccount, jobID),
CProjectAccount);
if (project)
{
DB_ObjectWatcher watcher(project);
// update the project array TCS 9/11/00
// this happens during posting so it doesn't need a server update
project->AddToAllowanceArray(GetDBID(), removeItem);
}
}
// adjust the status and stored project ID
if (removeItem)
{
SetStatus(status_InUse);
mMainAccount = 0;
}
else if (mStatus == status_Entered || mStatus == status_InUse)
{
SetStatus(status_Awarded);
}
if (jobClass == id_ProjectAccount && !removeItem)
mMainAccount = jobID; // TCS 9/10/00
MakeDirty();
// we also need to update the transaction array TCS 3/12/02
DB_ListManager::ChangeInMenus(this, cDontSortArray);
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 CAllowance::SetCompletedStatus(const Boolean removeItem)
{
UInt8 saveType = PrepareViewerDisplay();
if (removeItem)
{
if (mAmountPaid.IsPositive())
SetStatus(status_PartPaid);
else if (HasBeenReceivableBilled())
SetStatus(status_ReceivableBilled);
else
SetStatus(status_Awarded);
}
else
SetStatus(status_Completed);
UpdateViewerDisplay(saveType);
}
/*********************************************************************************
CanBeTandMBilled TCS 7/2/01
return whether this transaction can be used for allowance billing
*********************************************************************************/
Boolean CAllowance::CanBeTandMBilled() const
{
switch (mStatus)
{
case status_Entered:
case status_Awarded:
case status_InUse:
case status_Started:
case status_ReceivableBilled:
case status_PartPaid:
case status_Paid:
case status_Completed:
return true;
break;
case status_Void:
case status_Planned:
return false;
break;
default:
TCS_DebugAlert("Oops, invalid case in CAllowance::CanBeTandMBilled!");
return false;
break;
}
}
/*********************************************************************************
CalculateAmountDue TCS 8/8/02
calculate the actual billing amount. We have to adjust for minimum and
maximum limits, and also subtract previous billed amount.
*********************************************************************************/
CMoney CAllowance::CalculateAmountDue(const CMoney materialAmount, const CMoney otherCostAmount)
{
CMoney totalCost = materialAmount + otherCostAmount; // TCS 8/9/02
CMoney grossAmount = mGrossAmount * mQuantity;
CMoney zeroAmount, outAmount;
// calculate due amount, which depends on calc method
switch (mConditions)
{
case condition_NoCharge: // note difference from change order billing.
case condition_FirmPrice: // since we bill for the difference and the estimate already
case condition_Credit: // includes the fixed cost, there's nothing more to bill
outAmount = 0;
break;
case condition_TotalCost:
outAmount = totalCost - grossAmount - GetBilledAmount();
break;
case condition_CostWithMin:
outAmount = TCS_MAX(totalCost, GetMinMaxAmount()) - grossAmount - GetBilledAmount();
break;
case condition_CostWithMax:
outAmount = TCS_MIN(totalCost, GetMinMaxAmount()) - grossAmount - GetBilledAmount();
break;
case condition_Materialonly:
outAmount = materialAmount - grossAmount - GetBilledAmount();
break;
case condition_MaterialWithMin:
outAmount = TCS_MAX(materialAmount, GetMinMaxAmount()) - grossAmount - GetBilledAmount();
break;
case condition_MaterialWithMax:
outAmount = TCS_MIN(materialAmount, GetMinMaxAmount()) - grossAmount - GetBilledAmount();
break;
default:
TCS_DebugAlert("Oops, bad case in CAllowance::CalculateAmountDue!");
outAmount = 0;
break;
}
return outAmount;
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
PostRecordActivated
post info from a newly created or activated transaction
*********************************************************************************/
void CAllowance::PostRecordActivated(const UInt8 creationType)
{
PostAllowance();
UpdateEstimate();
// let the superclass do any posting. Note that we bypass
// CChangeOrder
CBreakdownTransaction::PostRecordActivated(creationType);
}
/*********************************************************************************
PostRecordCancelled TCS 9/24/98
post info from a deleted or voided transaction
*********************************************************************************/
void CAllowance::PostRecordCancelled(const UInt8 cancelType)
{
PostAllowance(cRemoveItem);
UpdateEstimate(cRemoveItem);
// let the superclass do any posting. Note that we bypass
// CChangeOrder
CBreakdownTransaction::PostRecordCancelled(cancelType);
}
/*********************************************************************************
PostRecordChanging
a record will be changing. Post the change.
*********************************************************************************/
void CAllowance::PostRecordChanging(const Boolean accountChanging, const Boolean jobChanging)
{
PostAllowance(cRemoveItem);
UpdateEstimate(cRemoveItem);
// let the superclass do any posting. Note that we bypass
// CChangeOrder
CBreakdownTransaction::PostRecordChanging(accountChanging, jobChanging);
}
/*********************************************************************************
PostRecordChanged
a record has changed. Post it.
*********************************************************************************/
void CAllowance::PostRecordChanged(const CMoney &oldAmount, const Boolean accountChanged,
const Boolean jobChanged)
{
PostAllowance();
UpdateEstimate();
// let the superclass do any posting. Note that we bypass
// CChangeOrder
CBreakdownTransaction::PostRecordChanged(oldAmount, accountChanged, jobChanged);
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
PostAllowance moved TCS 12/14/99 rev TCS 5/17/00
a allowance has changed. Post it.
*********************************************************************************/
void CAllowance::PostAllowance(const Boolean removeItem)
{
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
CProjectAccount *project = nil;
// start by finding the project account
if (mMainAccount)
{
project = TCS_SAFE_CAST(gDBFile->GetOneObject(id_ProjectAccount,
mMainAccount), CProjectAccount);
}
if (project)
{
DB_ObjectWatcher watcher(project);
// add this transaction to the project's array.
// note that we don't need to add/remove from dbase since
// AddToObjectIDArray already does that
project->AddToAllowanceArray(GetDBID(), removeItem);
}
}
/*********************************************************************************
UpdateEstimate TCS 2/11/03
update the estimate which includes this allowance
*********************************************************************************/
void CAllowance::UpdateEstimate(const Boolean removeItem)
{
if (mEstimate)
{
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
CEstimate *estimate =
TCS_SAFE_CAST(gDBFile->GetOneObject(id_Estimate, mEstimate), CEstimate);
if (estimate)
{
DB_ObjectWatcher watcher(estimate);
if (removeItem)
{
estimate->UpdateLineItem(costtype_allowance, GetDBID(), 0, 0, 0, mCostPerUnit);
}
else
{
estimate->UpdateLineItem(costtype_allowance, GetDBID(), GetAmount(),
mLaborHours, mCrewSize, mCostPerUnit);
}
}
else
mEstimate = 0;
gDBFile->HandleRecordChanged(estimate); // TCS 5/7/03
}
}
/*********************************************************************************
FetchComponentCosts TCS 2/10/03
fill in a detailed breakdown of estimated costs for this bid
*********************************************************************************/
CMoney CAllowance::FetchComponentCosts(SAssemblyUpdateInfo &info, const CMoney &inQuantity)
{
if (mBreakdownArray.GetCount() > 0)
THE_SUPERCLASS::FetchComponentCosts(info, inQuantity);
else
info.materialCost += GetAmount() * inQuantity;
return GetAmount();
}
/*********************************************************************************
WriteContractSpecs TCS 7/18/03
fill in specs for a contract. We use the contract text field, and do
the usual text substitution on it.
*********************************************************************************/
void CAllowance::WriteContractSpecs(CTextOutputStream &stream, const DBid /*subcontractType*/,
const Boolean includeAllowances, const Boolean /*includeBids*/,
const Boolean /*includeCatBreakdowns*/, const Boolean /*includeUnlisted*/) const
{
if (includeAllowances)
{
CTextString specsText;
if (mContractText.Length())
{
CContractPreferences *prefs =
TCS_SAFE_CAST(gDBFile->GetFirstObject(id_ContractPrefs),
CContractPreferences);
TCS_FailNILMsg(prefs, TCS_GetErrString(errID_BadPrefs));
DB_ObjectWatcher watcher(prefs);
specsText = prefs->DoSpecSubstitutions(mContractText, mQuantity,
contract_approx, mAmount, contract_allowance,
cEmptyString, 0);
}
else if (mDetails.Length())
{
specsText = mDetails;
}
else
{
specsText = GetMenuName();
}
stream.WriteString(specsText);
stream.WriteEndOfLine();
}
}
/*********************************************************************************
FillDataReport TCS 9/6/02
fill in a diagnostic table that shows data field values.
*********************************************************************************/
void CAllowance::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);
FillFieldTagRow(table, stream, tag_quantity, cMoneySize, mQuantity.GetNumberString());
FillFieldBitRow(table, stream, tag_unitcost, mCostPerUnit, true);
FillFieldStockRow(table, stream, stockID_Padding, -7, SInt32(allowanceFiller));
FillFieldStockRow(table, stream, stockID_Padding, cCharSize, SInt32(mAllowancePadding));
FillFieldObjectIDRow(table, stream, tag_estimate, mEstimate, id_Estimate);
FillEndSafetyTag(table, stream, mEndSafetyTag);
}
|