Link to: header | transactions
directory
Copyright Turtle Creek Software 1996-2006. All Rights Reserved.
Comments
CTimeLog
This class manages time tracking and time billing in the Goldenseal accounting software,
time tracking software, time
billing software and job costing software.
Each record a time log where hours are entered for equipment, labor or subcontractor hours.
Costs are posted from here to job costing, T&M billing, payroll, and subcontractor
accounts payable.
This class includes time management functions for Goldenseal payroll software and
job costing software. It also provides time quantities for time tracking and time billing.
SUPERCLASS = CExpenseTransaction
Constructor
/*********************************************************************************
constructor
*********************************************************************************/
CTimeLog::CTimeLog()
{
mTimeUsed = mJobCostAmount = 0;
mTimeUnit = time_hour;
mConditions = condition_None;
mAmountBilled = mAmountPaid = 0;
}
Source Code
/*********************************************************************************
CopyFrom
copy the data members from the passed object. This is used to implement
duplicate. source should be an object of the same class as this object
*********************************************************************************/
void CTimeLog::CopyFrom(DB_PersistentObject *source, const UInt8 copyFlags)
{
THE_SUPERCLASS::CopyFrom(source, copyFlags);
CTimeLog *src = TCS_SAFE_CAST(source, CTimeLog);
TCS_FailNILMsg(src, TCS_GetErrString(errID_BadRecord));
mDetails = src->mDetails; // TCS 1/30/03
TCS_BlockMove(&src->mTimeUsed, &mTimeUsed, cCopyFileLength);
}/*********************************************************************************
GetFileLength
return the file length used by this object
*********************************************************************************/
NeoSize CTimeLog::GetFileLength(const CNeoFormat *aFormat) const
{
NeoVersion version = GetVersion();
if (version == 1)
return THE_SUPERCLASS::GetFileLength(aFormat) + cFileLength;
else
{
return THE_SUPERCLASS::GetFileLength(aFormat) + // TCS 1/30/03
mDetails.LongFileLength(cMaximumTextLen) +
cFileLength;
}
}/*********************************************************************************
GetMemberValue
return the value of the member with the given tag
*********************************************************************************/
Boolean CTimeLog::GetMemberValue(const TagType aTag, const TagType aType,
void *aValue) const
{
CMoney amount = 0;
switch (aTag)
{
case tag_conditions:
return ConvertEnumMember(mConditions, MENU_TimeLogConditions, aValue, aType);
break;
case tag_breakdown: // TCS 4/3/00
return ConvertEnumMember(mBreakdownType, MENU_TimeCatItemBreakdown, aValue, aType);
break;
case tag_timeused:
return ConvertMember(&mTimeUsed, type_number, aValue, aType);
break;
case tag_jobcostamount:
return ConvertMember(&mJobCostAmount, type_money, aValue, aType);
break;
case tag_amountbilled:
return ConvertMember(&mAmountBilled, type_money, aValue, aType);
break;
case tag_amountpaid:
return ConvertMember(&mAmountPaid, type_money, aValue, aType);
break;
case tag_details: // TCS 1/30/03
return ConvertMember(&mDetails, type_longcstring, aValue, aType);
break;
case tag_amountdue:
amount = mAmountBilled - mAmountPaid;
return ConvertMember(&amount, type_money, aValue, aType);
break;
case tag_wageperunit:
amount = GetWagePerUnit();
return ConvertMember(&amount, type_money, aValue, aType);
break;
case tag_jobcostperunit:
amount = GetJobCostPerUnit();
return ConvertMember(&amount, type_money, aValue, aType);
break;
case tag_tandmperunit:
amount = GetTandMPerUnit();
return ConvertMember(&amount, type_money, aValue, aType);
break;
case tag_wageperhour:
amount = GetWagePerHour();
return ConvertMember(&amount, type_money, aValue, aType);
break;
case tag_jobcostperhour:
amount = GetJobCostPerHour();
return ConvertMember(&amount, type_money, aValue, aType);
break;
case tag_tandmperhour:
amount = GetTandMPerHour();
return ConvertMember(&amount, type_money, aValue, aType);
break;
default:
return THE_SUPERCLASS::GetMemberValue(aTag, aType, aValue);
break;
}
}/*********************************************************************************
SetMemberValue
set the value of the member with the given tag
*********************************************************************************/
Boolean CTimeLog::SetMemberValue(const TagType aTag, const TagType aType,
const void *aValue)
{
switch (aTag)
{
case tag_timeunit:
return ConvertMember(aValue, aType, &mTimeUnit, type_enum);
break;
case tag_conditions: // moved TCS 9/29/02
return ConvertMember(aValue, aType, &mConditions, type_enum);
break;
case tag_jobcostamount:
return ConvertMember(aValue, aType, &mJobCostAmount, type_money);
break;
case tag_timeused:
return ConvertMember(aValue, aType, &mTimeUsed, type_number);
break;
case tag_amountbilled:
return ConvertMember(aValue, aType, &mAmountBilled, type_money);
break;
case tag_amountpaid:
return ConvertMember(aValue, aType, &mAmountPaid, type_money);
break;
case tag_details: // TCS 1/30/03
return SafeConvertString(aValue, aType, &mDetails, type_longcstring);
break;
case tag_amountdue: // we don't ever need to set these
case tag_wageperunit:
case tag_jobcostperunit:
case tag_tandmperunit:
case tag_wageperhour:
case tag_jobcostperhour:
case tag_tandmperhour:
return true;
break;
default:
return THE_SUPERCLASS::SetMemberValue(aTag, aType, aValue);
break;
}
}/*********************************************************************************
ReadObject
read the persistent object's data in from a stream
*********************************************************************************/
void CTimeLog::ReadObject(CNeoStream *aStream, const TagType aTag)
{
TCS_FailNILMsg(aStream, TCS_GetErrString(errID_BadStream));
CNeoDebugImport checker(aStream, this); // TCS 2/24/00
THE_SUPERCLASS::ReadObject(aStream, aTag);
if (!IsIOValid()) // TCS 2/5/02
return;
NeoVersion version = GetVersion();
if (version > 1) // TCS 1/30/03
ReadLongTextFromStream(aStream, &mDetails);
/// aStream->ReadChunk(&mTimeUsed, cFileLength);
mTimeUsed.ReadFromStream(aStream); // mfs_sa rev 20feb2k3
mJobCostAmount.ReadFromStream(aStream);
mTimeUnit = aStream->ReadChar();
mConditions = aStream->ReadChar();
}/*********************************************************************************
WriteObject
write the persistent object's data to a stream
*********************************************************************************/
void CTimeLog::WriteObject(CNeoStream *aStream, const TagType aTag)
{
TCS_FailNILMsg(aStream, TCS_GetErrString(errID_BadStream));
CNeoDebugExport checker(aStream, this);
THE_SUPERCLASS::WriteObject(aStream, aTag);
NeoVersion version = GetVersion();
if (version > 1) // TCS 1/30/03
WriteLongTextToStream(aStream, mDetails, cMaximumTextLen);
/// aStream->WriteChunk(&mTimeUsed, cFileLength);
mTimeUsed.WriteToStream(aStream); // mfs_sa rev 20feb2k3
mJobCostAmount.WriteToStream(aStream);
aStream->WriteChar(mTimeUnit);
aStream->WriteChar(mConditions);
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
FinishImportCreate
fill in values after creation from an import
*********************************************************************************/
void CTimeLog::FinishImportCreate()
{
// let the superclass do its stuff
THE_SUPERCLASS::FinishImportCreate();
// the reference number must always be equal to the object id
mReferenceNum = GetDBID();
// do NOT adjust T&M or job cost rates!
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
CalculateTMBillingAmount (static) rev TCS 7/11/00
calculate the billing amount
*********************************************************************************/
CMoney CTimeLog::CalculateTMBillingAmount(const DBClass logClass, const CMoney &billedUnits,
const DBid accountID, const UInt8 timeUnit, const DBid billingRateID,
const CMoney &baseAmount, const CMoney &extraAmount)
{
CMoney amount(0,0),
accountRate;
// sanity check
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
// fetch info from fields
DBClass rateClass = CBillingRate::GetBillingRateClass(logClass);
DBClass accountClass = DB_ClassDescriptor::GetCostSupplier(logClass); // rev 7/11/00
if (billingRateID)
{
// we have a job cost rate, so it can compute the cost
CBillingRate *rate = TCS_SAFE_CAST(gDBFile->GetOneObject(rateClass,
billingRateID), CBillingRate);
if (rate)
{
// we have a billing rate, so it can compute the cost
DB_ObjectWatcher watcher(rate);
if (rate->HasVariableRate())
{ // it's a variable rate, so the account provides the value
accountRate = FetchAccountRate(tag_billingamount, accountClass, accountID);
amount = rate->ComputeBillingAmount(billedUnits, timeUnit, baseAmount,
extraAmount, accountRate);
}
else // it's a simple rate, so the rate can compute things
amount = rate->ComputeBillingAmount(billedUnits, timeUnit, baseAmount,
extraAmount);
}
}
// fill in the computed amount
return amount;
}
/*********************************************************************************
CalculateJobCostAmount
calculate the job cost amount from a given amount and billing rate
*********************************************************************************/
CMoney CTimeLog::CalculateJobCostAmount(const DBClass logClass, const CMoney &billedUnits,
const DBid accountID, const UInt8 timeUnit, const DBid billingRateID,
const CMoney &baseAmount, const CMoney &extraAmount)
{
CMoney amount(0,0),
accountRate;
// sanity check
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
// fetch info from fields
DBClass rateClass = CBillingRate::GetBillingRateClass(logClass);
DBClass accountClass = DB_ClassDescriptor::GetCostSupplier(logClass); // rev 7/11/00
if (billingRateID)
{
// we have a job cost rate, so it can compute the cost
CBillingRate *rate = TCS_SAFE_CAST(gDBFile->GetOneObject(rateClass,
billingRateID), CBillingRate);
if (rate)
{
DB_ObjectWatcher watcher(rate);
if (rate->HasVariableRate())
{ // it's a variable rate, so the account provides the value
accountRate = FetchAccountRate(tag_jobcostamount, accountClass, accountID);
amount = rate->ComputeBillingAmount(billedUnits, timeUnit, baseAmount,
extraAmount, accountRate);
}
else // it's a simple rate, so the rate can compute things
amount = rate->ComputeBillingAmount(billedUnits, timeUnit, baseAmount,
extraAmount);
}
}
return amount;
}/*********************************************************************************
FetchAccountRate (static) rev TCS 7/11/00
fetch a variable wage, job cost or billing rate from the cost account
*********************************************************************************/
CMoney CTimeLog::FetchAccountRate(const TagType tag, const DBClass classID,
const DBid accountID)
{
// sanity check
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
CMoney amount(0,0);
// if we have an account, fetch info from it
if (classID && accountID)
{
DB_PersistentObject *account = gDBFile->GetOneObject(classID, accountID);
TCS_FailNILMsg(account, TCS_GetErrString(errID_BadAccount));
DB_ObjectWatcher watcher(account);
TCS_ASSERTMsg(account->GetMemberValue(tag, type_money, &amount),
TCS_GetValueErrString(tag));
}
return amount;
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
GetWagePerUnit TCS 9/13/99
return the wage rate per time unit. This is the net rate, including overtime
*********************************************************************************/
CMoney CTimeLog::GetWagePerUnit() const
{
if (!mTimeUsed.IsZero())
return mAmount / mTimeUsed;
else
return 0;
}
/*********************************************************************************
GetJobCostPerUnit TCS 9/13/99
return the job cost amount per time unit.
*********************************************************************************/
CMoney CTimeLog::GetJobCostPerUnit() const
{
if (!mTimeUsed.IsZero())
return GetJobCostAmount() / mTimeUsed;
else
return 0;
}
/*********************************************************************************
GetTandMPerUnit TCS 9/13/99
return the t&m billing amount per time unit.
*********************************************************************************/
CMoney CTimeLog::GetTandMPerUnit() const
{
if (!mTimeUsed.IsZero())
return GetTandMAmount(false, false) / mTimeUsed;
else
return 0;
}
/*********************************************************************************
GetWagePerHour TCS 9/13/99
return the wage rate per hour. This is the net rate, including overtime
*********************************************************************************/
CMoney CTimeLog::GetWagePerHour() const
{
CMoney unitAmount = GetWagePerUnit();
unitAmount.AdjustForPeriod(mTimeUnit, time_hour);
return unitAmount;
}
/*********************************************************************************
GetJobCostPerHour TCS 9/13/99
return the job cost amount per hour
*********************************************************************************/
CMoney CTimeLog::GetJobCostPerHour() const
{
CMoney unitAmount = GetJobCostPerUnit();
unitAmount.AdjustForPeriod(mTimeUnit, time_hour);
return unitAmount;
}
/*********************************************************************************
GetTandMPerHour TCS 9/13/99
return the t&m billing amount per hour
*********************************************************************************/
CMoney CTimeLog::GetTandMPerHour() const
{
CMoney unitAmount = GetTandMPerUnit();
unitAmount.AdjustForPeriod(mTimeUnit, time_hour);
return unitAmount;
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
FillDataReport TCS 9/6/02
fill in a diagnostic table that shows data field values.
*********************************************************************************/
void CTimeLog::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();
if (version > 1)
FillFieldStringRow(table, stream, tag_details, mDetails, true);
FillFieldTagRow(table, stream, tag_timeused, cMoneySize, mTimeUsed.GetNumberString());
FillFieldTagRow(table, stream, tag_jobcostamount, cMoneySize, mJobCostAmount.GetCurrencyString());
FillFieldEnumRow(table, stream, tag_timeunit, mTimeUnit, MENU_HourToYearTimeUnits);
FillFieldEnumRow(table, stream, tag_conditions, mConditions, MENU_TimeLogConditions);
}
|