Accounting Software
Small Business Software Estimating Software
Inventory SoftwareInventory Tracking SoftwareInventory Control SoftwareInventory Management SoftwareConstruction Management SoftwareProject Management SoftwareBusiness Management Software

Time Logs (Source Code)

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);
}